package com.szcinda.service.dto.ghOrder;

import com.szcinda.controller.Result;
import com.szcinda.controller.params.QueryDto;
import com.szcinda.repository.*;
import com.szcinda.service.DateUtils;
import com.szcinda.service.PageResult;
import com.szcinda.service.SnowFlakeFactory;
import com.szcinda.service.TypeStringUtils;
import com.szcinda.service.dto.analysis.OrderAnalysisServiceImpl;
import com.szcinda.service.dto.calculatePrice.CalculateDto;
import com.szcinda.service.dto.calculatePrice.CalculateService;
import com.szcinda.service.dto.calculatePrice.PriceDto;
import com.szcinda.service.dto.client.ClientVehiclePriceDto;
import com.szcinda.service.dto.history.GhOrderExportVo;
import com.szcinda.service.dto.idGenerator.IdGeneratorService;
import com.szcinda.service.dto.log.LogCreateDto;
import com.szcinda.service.dto.log.LogService;
import com.szcinda.service.dto.log.OperateOrderDto;
import com.szcinda.service.dto.organization.OrganizationService;
import com.szcinda.service.dto.role.RoleRepository;
import com.szcinda.service.dto.zadOrder.ReCalculateFeeParams;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Predicate;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import static com.szcinda.service.dto.zadOrder.ZadOrderServiceImpl.getCurrencyV2;
import static com.szcinda.service.dto.zadOrder.ZadOrderServiceImpl.getMoney;


@Service
@Transactional
public class GhOrderServiceImpl implements GhOrderService {

    private final Logger logger = LoggerFactory.getLogger(GhOrderServiceImpl.class);

    private final GhOrderRepository ghOrderRepository;
    private final SnowFlakeFactory snowFlakeFactory;
    private final UserRepository userRepository;
    private final ClientRepository clientRepository;
    private final CarrierRepository carrierRepository;
    private final OrderFeeRepository orderFeeRepository;
    private final OrganizationService organizationService;
    private final LogService logService;
    private final FeeItemRepository feeItemRepository;
    private final OrganizationRepository organizationRepository;
    private final BaoGuanFeeRepository baoGuanFeeRepository;
    private final RateRepository rateRepository;
    private final BusinessCodeRepository businessCodeRepository;
    private final ClientVehiclePriceRepository clientVehiclePriceRepository;
    private final RoleRepository roleRepository;
    private final CalculateService calculateService;
    private final LinePriceRepository linePriceRepository;
    private final ExportLogRepository exportLogRepository;

    public GhOrderServiceImpl(GhOrderRepository ghOrderRepository, UserRepository userRepository, ClientRepository clientRepository, CarrierRepository carrierRepository, OrderFeeRepository orderFeeRepository, OrganizationService organizationService, LogService logService, FeeItemRepository feeItemRepository, OrganizationRepository organizationRepository, BaoGuanFeeRepository baoGuanFeeRepository, RateRepository rateRepository, BusinessCodeRepository businessCodeRepository, ClientVehiclePriceRepository clientVehiclePriceRepository, RoleRepository roleRepository, CalculateService calculateService, LinePriceRepository linePriceRepository, ExportLogRepository exportLogRepository) {
        this.ghOrderRepository = ghOrderRepository;
        this.userRepository = userRepository;
        this.clientRepository = clientRepository;
        this.carrierRepository = carrierRepository;
        this.orderFeeRepository = orderFeeRepository;
        this.organizationService = organizationService;
        this.logService = logService;
        this.feeItemRepository = feeItemRepository;
        this.organizationRepository = organizationRepository;
        this.baoGuanFeeRepository = baoGuanFeeRepository;
        this.rateRepository = rateRepository;
        this.businessCodeRepository = businessCodeRepository;
        this.clientVehiclePriceRepository = clientVehiclePriceRepository;
        this.roleRepository = roleRepository;
        this.calculateService = calculateService;
        this.linePriceRepository = linePriceRepository;
        this.exportLogRepository = exportLogRepository;
        this.snowFlakeFactory = SnowFlakeFactory.getInstance();
    }

    public static final DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");

    public static final DateTimeFormatter df2 = DateTimeFormatter.ofPattern("yyMMdd");

    @Override
    public void create(GhOrderCreateDto createDto) {
        Assert.isTrue(StringUtils.hasText(createDto.getClientId()), "客户必选");
        Assert.isTrue(StringUtils.hasText(createDto.getCalculateType()), "计费方式必选");
        Assert.isTrue(StringUtils.hasText(createDto.getBookNumber()), "订舱号必填");
        Assert.isTrue(StringUtils.hasText(createDto.getBusinessCode()), "业务类型必填");
        Organization organization = organizationService.getById(createDto.getOrganizationId());
        // 检查订舱号是否存在
        GhOrder record = ghOrderRepository.findFirstByOrganizationIdAndBookNumber(createDto.getOrganizationId(), createDto.getBookNumber());
        Assert.isTrue(record == null, String.format("当前机构已存在订舱号【%s】", createDto.getBookNumber()));
        if (StringUtils.hasText(createDto.getOrderNumber())) {
            record = ghOrderRepository.findByOrderNumber(createDto.getOrderNumber());
            Assert.isTrue(record != null, String.format("根据订单编号【%s】找不到记录", createDto.getOrderNumber()));
            Assert.isTrue(record.getStatus().equals(OrderStatus.UN_CONFIRM), String.format("订单【%s】已锁定，不能覆盖更新", createDto.getOrderNumber()));
            BeanUtils.copyProperties(createDto, record, "id");
            ghOrderRepository.save(record);
            return;
        }
        BusinessCode businessCode = businessCodeRepository.findByName(createDto.getBusinessCode());
        String businessCodePre = "";
        if (businessCode != null) {
            businessCodePre = businessCode.getPrefix();
        }
        User user = userRepository.findById(createDto.getOpId());
        GhOrder ghOrder = new GhOrder();
        BeanUtils.copyProperties(createDto, ghOrder);
        String prefix = "";
        if (StringUtils.hasText(organization.getPrefix())) {
            prefix = organization.getPrefix();
        }
        // 获取今天共有多少单
        LocalDate now = LocalDate.now();
        Specification<GhOrder> specification = ((root, criteriaQuery, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            Predicate timeStart = criteriaBuilder.greaterThanOrEqualTo(root.get("createTime"), now.atStartOfDay());
            predicates.add(timeStart);
            Predicate timeEnd = criteriaBuilder.lessThan(root.get("createTime"), now.plusDays(1).atStartOfDay());
            predicates.add(timeEnd);
            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        });
        List<GhOrder> historyList = ghOrderRepository.findAll(specification);
        logger.info(String.format("今天的单量一共：【%d】条", historyList.size()));
        // 生成下一个单号
        int count = historyList.size();
        String orderNumber;
        while (true) {
            orderNumber = prefix + businessCodePre + df2.format(LocalDateTime.now()) + String.format("%03d", count + 1);
            logger.info(String.format("生成的单号是：【%s】", orderNumber));
            String finalOrderNumber = orderNumber;
            if (historyList.stream().noneMatch(re -> re.getOrderNumber().equals(finalOrderNumber))) {
                break;
            } else {
                count++;
            }
        }
        ghOrder.setOrderNumber(orderNumber);
        Client client = clientRepository.findById(createDto.getClientId());
        ghOrder.setClientName(client.getName());
        if (StringUtils.hasText(ghOrder.getCarrierId())) {
            Carrier carrier = carrierRepository.findById(ghOrder.getCarrierId());
            ghOrder.setCarrierName(carrier.getName());
        }
        ghOrder.setOrganizationName(organization.getName());
        ghOrder.setId(snowFlakeFactory.nextId("GO"));
        ghOrder.setUserId(user.getId());
        ghOrder.setUserName(user.getNickName());
        ghOrder.setStatus(OrderStatus.UN_CONFIRM);
        ghOrderRepository.save(ghOrder);

        BaoGuanFee baoGuanFee = baoGuanFeeRepository.findByBelongId(ghOrder.getId());
        if (baoGuanFee == null) {
            baoGuanFee = new BaoGuanFee();
            baoGuanFee.setId(snowFlakeFactory.nextId("BG"));
            baoGuanFee.setBelongId(ghOrder.getId());
        }
        baoGuanFee.setHomeFee(createDto.getHomeFee());
        baoGuanFee.setSheetFee(createDto.getSheetFee());
        baoGuanFee.setHomeCount(createDto.getHomeCount());
        baoGuanFee.setSheetCount(createDto.getSheetCount());
        baoGuanFeeRepository.save(baoGuanFee);

        // 应收
        List<GhOrderCreateDto.FeeDto> feeList = createDto.getFeeList();
        if (feeList != null && feeList.size() > 0) {
            List<OrderFee> fees = new ArrayList<>();
            feeList.forEach(feeDto -> {
                OrderFee fee = new OrderFee();
                BeanUtils.copyProperties(feeDto, fee);
                fee.setId(snowFlakeFactory.nextId("OF"));
                fee.setOrderId(ghOrder.getId());
                // 系统发车时间为准，后面方便于统计应付费用
                if (ghOrder.getActDepartureTime() != null) {
                    fee.setCreateTime(ghOrder.getActDepartureTime().atStartOfDay());
                }
                fee.setType(TypeStringUtils.feeInType);
                fees.add(fee);
                // 检查费用科目是否存在，如果不存在则新增
                FeeItem feeItem = feeItemRepository.findByName(fee.getFeeName().trim());
                if (feeItem == null && StringUtils.hasText(fee.getFeeName()) && fee.getFeeName().trim().length() > 0 && "报关费".equals(fee.getFeeName().trim()) && "报关联单费".equals(fee.getFeeName().trim()) && "超期堆存费".equals(fee.getFeeName().trim())) {
                    feeItem = new FeeItem();
                    feeItem.setId(snowFlakeFactory.nextId("FI"));
                    feeItem.setName(fee.getFeeName());
                    feeItemRepository.save(feeItem);
                }
            });
            orderFeeRepository.save(fees);
        }
        HashSet<String> carrierNames = new HashSet<>();
        // 应付
        List<GhOrderCreateDto.FeeDto> outFeeList = createDto.getOutFeeList();
        if (outFeeList != null && outFeeList.size() > 0) {
            List<OrderFee> fees = new ArrayList<>();
            outFeeList.forEach(feeDto -> {
                OrderFee fee = new OrderFee();
                BeanUtils.copyProperties(feeDto, fee);
                fee.setId(snowFlakeFactory.nextId("OF"));
                fee.setOrderId(ghOrder.getId());
                fee.setCarrierId(feeDto.getCarrierId());
                if (StringUtils.hasText(feeDto.getCarrierId())) {
                    carrierNames.add(feeDto.getCarrierId());
                }
                if (ghOrder.getActDepartureTime() != null) {
                    // 以发车时间作为创建时间，后面统计需要按照发车时间统计，设置为发车时间方便汇总
                    fee.setCreateTime(ghOrder.getActDepartureTime().atStartOfDay());
                }
                fee.setType(TypeStringUtils.feeOutType);
                fees.add(fee);
                // 检查费用科目是否存在，如果不存在则新增
                FeeItem feeItem = feeItemRepository.findByName(fee.getFeeName().trim());
                if (feeItem == null && StringUtils.hasText(fee.getFeeName()) && fee.getFeeName().trim().length() > 0 && "报关费".equals(fee.getFeeName().trim()) && "报关联单费".equals(fee.getFeeName().trim()) && "超期堆存费".equals(fee.getFeeName().trim())) {
                    feeItem = new FeeItem();
                    feeItem.setId(snowFlakeFactory.nextId("FI"));
                    feeItem.setName(fee.getFeeName());
                    feeItemRepository.save(feeItem);
                }
            });
            orderFeeRepository.save(fees);
        }
        // 保存车型派送费
        clientVehiclePriceRepository.deleteByBelongId(ghOrder.getId());
        List<ClientVehiclePriceDto> vehiclePrices = createDto.getVehiclePrices();
        if (vehiclePrices != null && vehiclePrices.size() > 0) {
            for (ClientVehiclePriceDto vehiclePrice : vehiclePrices) {
                ClientVehiclePrice vp = new ClientVehiclePrice();
                vp.setId(snowFlakeFactory.nextId("VP"));
                vp.setBelongId(ghOrder.getId());
                vp.setName(vehiclePrice.getName());
                vp.setAmount(vehiclePrice.getAmount());
                clientVehiclePriceRepository.save(vp);
            }
        }
        ghOrder.setCarrierName(String.join(",", carrierNames));
        ghOrderRepository.save(ghOrder);
        LogCreateDto logCreateDto = new LogCreateDto(user.getId(), user.getNickName(), "新增综合物流", ghOrder.getOrderNumber());
        logService.create(logCreateDto);
    }

    @Override
    public void update(GhOrderUpdateDto updateDto) {
        Organization organization = organizationService.getById(updateDto.getOrganizationId());
        GhOrder record = ghOrderRepository.findFirstByOrganizationIdAndBookNumber(updateDto.getOrganizationId(), updateDto.getBookNumber());
        // 判断是否是属于当前的订舱号
        Assert.isTrue(record == null || record.getId().equals(updateDto.getId()), String.format("当前机构已存在订舱号【%s】", updateDto.getBookNumber()));
        GhOrder ghOrder = ghOrderRepository.findById(updateDto.getId());
        BeanUtils.copyProperties(updateDto, ghOrder, "id");
        Client client = clientRepository.findById(updateDto.getClientId());
        ghOrder.setClientName(client.getName());
        ghOrder.setOrganizationName(organization.getName());
        ghOrderRepository.save(ghOrder);

        BaoGuanFee baoGuanFee = baoGuanFeeRepository.findByBelongId(ghOrder.getId());
        if (baoGuanFee == null) {
            baoGuanFee = new BaoGuanFee();
            baoGuanFee.setId(snowFlakeFactory.nextId("BG"));
            baoGuanFee.setBelongId(ghOrder.getId());
        }
        baoGuanFee.setHomeFee(updateDto.getHomeFee());
        baoGuanFee.setSheetFee(updateDto.getSheetFee());
        baoGuanFee.setHomeCount(updateDto.getHomeCount());
        baoGuanFee.setSheetCount(updateDto.getSheetCount());
        baoGuanFeeRepository.save(baoGuanFee);

        // 删除旧费用
        orderFeeRepository.deleteByOrderId(updateDto.getId());
        // 应收
        List<GhOrderUpdateDto.FeeDto> feeList = updateDto.getFeeList();
        if (feeList != null && feeList.size() > 0) {
            List<OrderFee> fees = new ArrayList<>();
            feeList.forEach(feeDto -> {
                OrderFee fee = new OrderFee();
                BeanUtils.copyProperties(feeDto, fee);
                fee.setId(snowFlakeFactory.nextId("OF"));
                fee.setOrderId(ghOrder.getId());
                fee.setType(TypeStringUtils.feeInType);
                fee.setStatus(feeDto.getStatus());
                // 系统发车时间为准，后面方便于统计应付费用
                if (ghOrder.getActDepartureTime() != null) {
                    fee.setCreateTime(ghOrder.getActDepartureTime().atStartOfDay());
                }
                fees.add(fee);
                // 检查费用科目是否存在，如果不存在则新增
                FeeItem feeItem = feeItemRepository.findByName(fee.getFeeName().trim());
                if (feeItem == null && StringUtils.hasText(fee.getFeeName()) && fee.getFeeName().trim().length() > 0 && (!"报关费".equals(fee.getFeeName().trim()) && !"报关联单费".equals(fee.getFeeName().trim()) && !"超期堆存费".equals(fee.getFeeName().trim()))) {
                    feeItem = new FeeItem();
                    feeItem.setId(snowFlakeFactory.nextId("FI"));
                    feeItem.setName(fee.getFeeName());
                    feeItemRepository.save(feeItem);
                }
            });
            orderFeeRepository.save(fees);
        }
        HashSet<String> carrierNames = new HashSet<>();
        // 应付
        List<GhOrderUpdateDto.FeeDto> outFeeList = updateDto.getOutFeeList();
        if (outFeeList != null && outFeeList.size() > 0) {
            List<OrderFee> fees = new ArrayList<>();
            outFeeList.forEach(feeDto -> {
                OrderFee fee = new OrderFee();
                BeanUtils.copyProperties(feeDto, fee);
                fee.setId(snowFlakeFactory.nextId("OF"));
                fee.setOrderId(ghOrder.getId());
                fee.setCarrierId(feeDto.getCarrierId());
                if (StringUtils.hasText(feeDto.getCarrierId())) {
                    carrierNames.add(feeDto.getCarrierId());
                }
                fee.setType(TypeStringUtils.feeOutType);
                fee.setStatus(feeDto.getStatus());
                if (ghOrder.getActDepartureTime() != null) {
                    // 以发车时间作为创建时间，后面统计需要按照发车时间统计，设置为发车时间方便汇总
                    fee.setCreateTime(ghOrder.getActDepartureTime().atStartOfDay());
                }
                fees.add(fee);
                // 检查费用科目是否存在，如果不存在则新增
                FeeItem feeItem = feeItemRepository.findByName(fee.getFeeName().trim());
                if (feeItem == null && StringUtils.hasText(fee.getFeeName()) && fee.getFeeName().trim().length() > 0 && (!"报关费".equals(fee.getFeeName().trim()) && !"报关联单费".equals(fee.getFeeName().trim()) && !"超期堆存费".equals(fee.getFeeName().trim()))) {
                    feeItem = new FeeItem();
                    feeItem.setId(snowFlakeFactory.nextId("FI"));
                    feeItem.setName(fee.getFeeName());
                    feeItemRepository.save(feeItem);
                }
            });
            orderFeeRepository.save(fees);
        }
        // 保存车型派送费
        clientVehiclePriceRepository.deleteByBelongId(ghOrder.getId());
        List<ClientVehiclePriceDto> vehiclePrices = updateDto.getVehiclePrices();
        if (vehiclePrices != null && vehiclePrices.size() > 0) {
            for (ClientVehiclePriceDto vehiclePrice : vehiclePrices) {
                ClientVehiclePrice vp = new ClientVehiclePrice();
                vp.setId(snowFlakeFactory.nextId("VP"));
                vp.setBelongId(ghOrder.getId());
                vp.setName(vehiclePrice.getName());
                vp.setAmount(vehiclePrice.getAmount());
                clientVehiclePriceRepository.save(vp);
            }
        }
        ghOrder.setCarrierName(String.join(",", carrierNames));
        ghOrderRepository.save(ghOrder);
        User user = userRepository.findById(updateDto.getOpId());
        LogCreateDto logCreateDto = new LogCreateDto(user.getId(), user.getNickName(), "修改综合物流", ghOrder.getOrderNumber());
        logService.create(logCreateDto);
    }


    @Override
    public void update(GhOrderUpdatePartDto updateDto) {
        GhOrder ghOrder = ghOrderRepository.findById(updateDto.getId());
        BeanUtils.copyProperties(updateDto, ghOrder, "id");
        ghOrderRepository.save(ghOrder);
        User op = userRepository.findById(updateDto.getOpId());
        if ("IN_OR_SETTLEMENT".equals(updateDto.getType()) && BillType.STATUS_YKP.equals(ghOrder.getInvoice())) {
            LogCreateDto logCreateDto = new LogCreateDto(op.getId(), op.getNickName(), "综合物流应收已开票", ghOrder.getOrderNumber());
            logService.create(logCreateDto);
        }
        if ("IN_OR_SETTLEMENT".equals(updateDto.getType()) && BillType.STATUS_YJS.equals(ghOrder.getSettlement())) {
            LogCreateDto logCreateDto = new LogCreateDto(op.getId(), op.getNickName(), "综合物流应收已结算", ghOrder.getOrderNumber());
            logService.create(logCreateDto);
            // 把订单状态锁定
            ghOrder.setStatus(OrderStatus.CONFIRMED);
            // 把所有应收的费用锁定
            List<OrderFee> fees = orderFeeRepository.findByOrderIdAndType(ghOrder.getId(), TypeStringUtils.feeInType);
            for (OrderFee fee : fees) {
                fee.setStatus(TypeStringUtils.feeLockStatus);
            }
            orderFeeRepository.save(fees);
            ghOrderRepository.save(ghOrder);
        }
        if ("IN_OR_SETTLEMENT".equals(updateDto.getType()) && BillType.STATUS_YKP.equals(ghOrder.getOutInvoice())) {
            LogCreateDto logCreateDto = new LogCreateDto(op.getId(), op.getNickName(), "综合物流应付已开票", ghOrder.getOrderNumber());
            logService.create(logCreateDto);
        }
        if ("IN_OR_SETTLEMENT".equals(updateDto.getType()) && BillType.STATUS_YJS.equals(ghOrder.getOutSettlement())) {
            LogCreateDto logCreateDto = new LogCreateDto(op.getId(), op.getNickName(), "综合物流应付已结算", ghOrder.getOrderNumber());
            logService.create(logCreateDto);
            // 把订单状态锁定
            ghOrder.setStatus(OrderStatus.CONFIRMED);
            // 把所有应付费用锁定
            List<OrderFee> fees = orderFeeRepository.findByOrderIdAndType(ghOrder.getId(), TypeStringUtils.feeOutType);
            for (OrderFee fee : fees) {
                fee.setStatus(TypeStringUtils.feeLockStatus);
            }
            orderFeeRepository.save(fees);
            ghOrderRepository.save(ghOrder);
        }
    }

    @Override
    public void delete(String id, String userId) {
        GhOrder ghOrder = ghOrderRepository.findById(id);
        ghOrderRepository.delete(ghOrder);
        User user = userRepository.findById(userId);
        LogCreateDto logCreateDto = new LogCreateDto(user.getId(), user.getNickName(), "删除综合物流", ghOrder.getOrderNumber());
        logService.create(logCreateDto);
    }

    @Override
    public PageResult<GhOrderDto> query(GhOrderQueryDto params) {
        Assert.hasText(params.getUserId(), "当前操作用户参数必填");
        Specification<GhOrder> specification = ((root, criteriaQuery, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            User user = userRepository.findById(params.getUserId());
            Role role = roleRepository.findById(user.getRoleId());
            if (RoleType.SUPER_ADMIN.equals(role.getName())) {
                // 得到所有的订单
                List<String> orgIds = organizationService.getAllOrgIds();
                Expression<String> exp = root.get("organizationId");
                predicates.add(exp.in(orgIds));
                if (!StringUtils.isEmpty(params.getOrganizationId())) {
                    Predicate organizationId = criteriaBuilder.equal(root.get("organizationId"), params.getOrganizationId());
                    predicates.add(organizationId);
                }
            } else if (RoleType.ADMIN.equals(role.getName())) {
                // 得到当前机构及子机构的所有订单
                List<String> orgIds = organizationService.getChildOrgIds(user.getOrganizationId());
                Expression<String> exp = root.get("organizationId");
                predicates.add(exp.in(orgIds));
                if (!StringUtils.isEmpty(params.getOrganizationId())) {
                    Predicate organizationId = criteriaBuilder.equal(root.get("organizationId"), params.getOrganizationId());
                    predicates.add(organizationId);
                }
            } else if (role.isEqualAdmin()) {
                // 授予了机构管理员权限
                List<String> orgIds = organizationService.getChildOrgIds(user.getOrganizationId());
                Expression<String> exp = root.get("organizationId");
                predicates.add(exp.in(orgIds));
                if (!StringUtils.isEmpty(params.getOrganizationId())) {
                    Predicate organizationId = criteriaBuilder.equal(root.get("organizationId"), params.getOrganizationId());
                    predicates.add(organizationId);
                }
            } else {
                // 得到属于用户当前机构的订单
                Expression<String> exp = root.get("organizationId");
                predicates.add(exp.in(Collections.singletonList(params.getOrganizationId())));
            }
            boolean isAdmin = RoleType.SUPER_ADMIN.equals(role.getName()) || RoleType.ADMIN.equals(role.getName()) || role.isEqualAdmin();
            if (!isAdmin) {
                // 如果不是管理员，只能看到自己的
                Predicate userId = criteriaBuilder.equal(root.get("userId"), params.getUserId());
                predicates.add(userId);
            }
            if (!StringUtils.isEmpty(params.getInvoice())) {
                Predicate invoice = criteriaBuilder.equal(root.get("invoice").as(String.class), params.getInvoice());
                predicates.add(invoice);
            }
            if (!StringUtils.isEmpty(params.getSettlement())) {
                Predicate settlement = criteriaBuilder.equal(root.get("settlement").as(String.class), params.getSettlement());
                predicates.add(settlement);
            }
            if (!StringUtils.isEmpty(params.getOutInvoice())) {
                Predicate outInvoice = criteriaBuilder.equal(root.get("outInvoice").as(String.class), params.getOutInvoice());
                predicates.add(outInvoice);
            }
            if (!StringUtils.isEmpty(params.getOutSettlement())) {
                Predicate outSettlement = criteriaBuilder.equal(root.get("outSettlement").as(String.class), params.getOutSettlement());
                predicates.add(outSettlement);
            }
            if (StringUtils.hasText(params.getDaiBan())) {
                //封装or语句
                List<Predicate> listOr = new ArrayList<>();
                if (TypeStringUtils.feeInType.equals(params.getType())) {
                    Predicate invoice = criteriaBuilder.equal(root.get("invoice").as(String.class), BillType.STATUS_WKP);
                    listOr.add(invoice);
                    Predicate settlement = criteriaBuilder.equal(root.get("settlement").as(String.class), BillType.STATUS_WJS);
                    listOr.add(settlement);
                } else {
                    Predicate outInvoice = criteriaBuilder.equal(root.get("outInvoice").as(String.class), BillType.STATUS_WKP);
                    listOr.add(outInvoice);
                    Predicate outSettlement = criteriaBuilder.equal(root.get("outSettlement").as(String.class), BillType.STATUS_WJS);
                    listOr.add(outSettlement);
                }
                Predicate[] arrayOr = new Predicate[listOr.size()];
                Predicate pre_Or = criteriaBuilder.or(listOr.toArray(arrayOr));
                predicates.add(pre_Or);
            }
            if (!StringUtils.isEmpty(params.getClientId())) {
                Predicate client = criteriaBuilder.equal(root.get("clientId"), params.getClientId());
                predicates.add(client);
            }
            if (!StringUtils.isEmpty(params.getCarrierId())) {
                Carrier carrier = carrierRepository.findById(params.getCarrierId());
                Predicate carrierId = criteriaBuilder.like(root.get("carrierName"), "%" + carrier.getName() + "%");
                predicates.add(carrierId);
            }
            if (!StringUtils.isEmpty(params.getOrderNumber())) {
                Predicate site = criteriaBuilder.like(root.get("orderNumber"), "%" + params.getOrderNumber().trim() + "%");
                predicates.add(site);
            }
            if (!StringUtils.isEmpty(params.getBookNumber())) {
                Predicate site = criteriaBuilder.like(root.get("bookNumber"), "%" + params.getBookNumber().trim() + "%");
                predicates.add(site);
            }
            if (params.getPickDateStart() != null) {
                Predicate timeStart = criteriaBuilder.greaterThanOrEqualTo(root.get("pickDate"), params.getPickDateStart());
                predicates.add(timeStart);
            }
            if (params.getPickDateEnd() != null) {
                Predicate timeEnd = criteriaBuilder.lessThan(root.get("pickDate"), params.getPickDateEnd().plusDays(1));
                predicates.add(timeEnd);
            }
            if (params.getCreateTimeStart() != null) {
                Predicate timeStart = criteriaBuilder.greaterThanOrEqualTo(root.get("createTime"), params.getCreateTimeStart().atStartOfDay());
                predicates.add(timeStart);
            }
            if (params.getCreateTimeEnd() != null) {
                Predicate timeEnd = criteriaBuilder.lessThan(root.get("createTime"), params.getCreateTimeEnd().plusDays(1).atStartOfDay());
                predicates.add(timeEnd);
            }
            if (params.getActDepartureTimeStart() != null) {
                Predicate timeStart = criteriaBuilder.greaterThanOrEqualTo(root.get("actDepartureTime"), params.getActDepartureTimeStart());
                predicates.add(timeStart);
            }
            if (params.getActDepartureTimeEnd() != null) {
                Predicate timeEnd = criteriaBuilder.lessThan(root.get("actDepartureTime"), params.getActDepartureTimeEnd().plusDays(1));
                predicates.add(timeEnd);
            }
            // 派送日期
            if (params.getReceiveDateStart() != null) {
                Predicate timeStart = criteriaBuilder.greaterThanOrEqualTo(root.get("receiveDate"), params.getReceiveDateStart());
                predicates.add(timeStart);
            }
            if (params.getReceiveDateEnd() != null) {
                Predicate timeEnd = criteriaBuilder.lessThan(root.get("receiveDate"), params.getReceiveDateEnd().plusDays(1));
                predicates.add(timeEnd);
            }
            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        });
        Sort order = new Sort(Sort.Direction.DESC, "createTime", "orderNumber");
        Pageable pageable = new PageRequest(params.getPage() - 1, params.getPageSize(), order);
        Page<GhOrder> details = ghOrderRepository.findAll(specification, pageable);
        List<GhOrder> ghOrders = details.getContent();
        List<String> ids = ghOrders.stream().map(GhOrder::getId).collect(Collectors.toList());
        List<ClientVehiclePrice> vehiclePrices = clientVehiclePriceRepository.findByBelongIdIn(ids);
        List<BaoGuanFee> baoGuanFees = baoGuanFeeRepository.findByBelongIdIn(ids);
        List<OrderFee> fees = orderFeeRepository.findByOrderIdIn(ids);
        List<GhOrderDto> dtos = new ArrayList<>();
        ghOrders.forEach(ghOrder -> {
            GhOrderDto dto = new GhOrderDto();
            BeanUtils.copyProperties(ghOrder, dto);
            BaoGuanFee guanFee = baoGuanFees.stream().filter(baoGuanFee -> baoGuanFee.getBelongId().equals(ghOrder.getId())).findFirst().orElse(null);
            if (guanFee != null) {
                dto.setHomeFee(guanFee.getHomeFee());
                dto.setHomeCount(guanFee.getHomeCount());
                dto.setSheetFee(guanFee.getSheetFee());
                dto.setSheetCount(guanFee.getSheetCount());
            }
            List<OrderFee> orderFees = fees.stream().filter(orderFee -> orderFee.getOrderId().equals(ghOrder.getId())).collect(Collectors.toList());
            if (orderFees.size() > 0) {
                List<GhOrderDto.FeeDto> feeDtos = new ArrayList<>();
                List<GhOrderDto.FeeDto> outFeeDtos = new ArrayList<>();
                orderFees.forEach(orderFee -> {
                    GhOrderDto.FeeDto feeDto = new GhOrderDto.FeeDto();
                    BeanUtils.copyProperties(orderFee, feeDto);
                    if (TypeStringUtils.feeInType.equals(orderFee.getType())) {
                        feeDtos.add(feeDto);
                    } else {
                        outFeeDtos.add(feeDto);
                    }
                });
                dto.setFeeList(feeDtos);
                dto.setOutFeeList(outFeeDtos);
            }
            List<ClientVehiclePrice> clientVehiclePrices = vehiclePrices.stream().filter(clientVehiclePrice -> clientVehiclePrice.getBelongId().equals(ghOrder.getId())).collect(Collectors.toList());
            if (clientVehiclePrices.size() > 0) {
                List<ClientVehiclePriceDto> vehiclePriceDtos = new ArrayList<>();
                for (ClientVehiclePrice clientVehiclePrice : clientVehiclePrices) {
                    ClientVehiclePriceDto vehiclePriceDto = new ClientVehiclePriceDto();
                    vehiclePriceDto.setName(clientVehiclePrice.getName());
                    vehiclePriceDto.setAmount(clientVehiclePrice.getAmount());
                    vehiclePriceDtos.add(vehiclePriceDto);
                }
                dto.setVehiclePrices(vehiclePriceDtos);
            }
            dtos.add(dto);
        });
        return PageResult.of(dtos, params.getPage(), params.getPageSize(), details.getTotalElements());
    }

    @Override
    public List<GhOrderDto> queryAll(GhOrderQueryDto params) {
        Specification<GhOrder> specification = ((root, criteriaQuery, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            User user = userRepository.findById(params.getUserId());
            Role role = roleRepository.findById(user.getRoleId());
            if (RoleType.SUPER_ADMIN.equals(role.getName())) {
                // 得到所有的订单
                List<String> orgIds = organizationService.getAllOrgIds();
                Expression<String> exp = root.get("organizationId");
                predicates.add(exp.in(orgIds));
                if (!StringUtils.isEmpty(params.getOrganizationId())) {
                    Predicate organizationId = criteriaBuilder.equal(root.get("organizationId"), params.getOrganizationId());
                    predicates.add(organizationId);
                }
            } else if (RoleType.ADMIN.equals(role.getName())) {
                // 得到当前机构及子机构的所有订单
                List<String> orgIds = organizationService.getChildOrgIds(user.getOrganizationId());
                Expression<String> exp = root.get("organizationId");
                predicates.add(exp.in(orgIds));
                if (!StringUtils.isEmpty(params.getOrganizationId())) {
                    Predicate organizationId = criteriaBuilder.equal(root.get("organizationId"), params.getOrganizationId());
                    predicates.add(organizationId);
                }
            } else if (role.isEqualAdmin()) {
                // 授予了机构管理员权限
                List<String> orgIds = organizationService.getChildOrgIds(user.getOrganizationId());
                Expression<String> exp = root.get("organizationId");
                predicates.add(exp.in(orgIds));
                if (!StringUtils.isEmpty(params.getOrganizationId())) {
                    Predicate organizationId = criteriaBuilder.equal(root.get("organizationId"), params.getOrganizationId());
                    predicates.add(organizationId);
                }
            } else {
                // 只查询当前机构的订单
                Predicate organizationId = criteriaBuilder.equal(root.get("organizationId"), params.getOrganizationId());
                predicates.add(organizationId);
                // 只能看到自己的订单
                Predicate userId = criteriaBuilder.equal(root.get("userId"), params.getUserId());
                predicates.add(userId);
            }
            if (!StringUtils.isEmpty(params.getInvoice())) {
                Predicate invoice = criteriaBuilder.equal(root.get("invoice").as(String.class), params.getInvoice());
                predicates.add(invoice);
            }
            if (!StringUtils.isEmpty(params.getSettlement())) {
                Predicate settlement = criteriaBuilder.equal(root.get("settlement").as(String.class), params.getSettlement());
                predicates.add(settlement);
            }
            if (!StringUtils.isEmpty(params.getOutInvoice())) {
                Predicate outInvoice = criteriaBuilder.equal(root.get("outInvoice").as(String.class), params.getOutInvoice());
                predicates.add(outInvoice);
            }
            if (!StringUtils.isEmpty(params.getOutSettlement())) {
                Predicate outSettlement = criteriaBuilder.equal(root.get("outSettlement").as(String.class), params.getOutSettlement());
                predicates.add(outSettlement);
            }
            if (StringUtils.hasText(params.getDaiBan())) {
                //封装or语句
                List<Predicate> listOr = new ArrayList<>();
                if (TypeStringUtils.feeInType.equals(params.getType())) {
                    Predicate invoice = criteriaBuilder.equal(root.get("invoice").as(String.class), BillType.STATUS_WKP);
                    listOr.add(invoice);
                    Predicate settlement = criteriaBuilder.equal(root.get("settlement").as(String.class), BillType.STATUS_WJS);
                    listOr.add(settlement);
                } else {
                    Predicate outInvoice = criteriaBuilder.equal(root.get("outInvoice").as(String.class), BillType.STATUS_WKP);
                    listOr.add(outInvoice);
                    Predicate outSettlement = criteriaBuilder.equal(root.get("outSettlement").as(String.class), BillType.STATUS_WJS);
                    listOr.add(outSettlement);
                }
                Predicate[] arrayOr = new Predicate[listOr.size()];
                Predicate pre_Or = criteriaBuilder.or(listOr.toArray(arrayOr));
                predicates.add(pre_Or);
            }
            if (!StringUtils.isEmpty(params.getClientId())) {
                Predicate client = criteriaBuilder.equal(root.get("clientId"), params.getClientId());
                predicates.add(client);
            }
            if (!StringUtils.isEmpty(params.getCarrierId())) {
                Carrier carrier = carrierRepository.findById(params.getCarrierId());
                Predicate carrierId = criteriaBuilder.like(root.get("carrierName"), "%" + carrier.getName() + "%");
                predicates.add(carrierId);
            }
            if (!StringUtils.isEmpty(params.getOrderNumber())) {
                Predicate site = criteriaBuilder.like(root.get("orderNumber"), "%" + params.getOrderNumber().trim() + "%");
                predicates.add(site);
            }
            if (!StringUtils.isEmpty(params.getBookNumber())) {
                Predicate site = criteriaBuilder.like(root.get("bookNumber"), "%" + params.getBookNumber().trim() + "%");
                predicates.add(site);
            }
            if (params.getPickDateStart() != null) {
                Predicate timeStart = criteriaBuilder.greaterThanOrEqualTo(root.get("pickDate"), params.getPickDateStart());
                predicates.add(timeStart);
            }
            if (params.getPickDateEnd() != null) {
                Predicate timeEnd = criteriaBuilder.lessThan(root.get("pickDate"), params.getPickDateEnd().plusDays(1));
                predicates.add(timeEnd);
            }
            if (params.getCreateTimeStart() != null) {
                Predicate timeStart = criteriaBuilder.greaterThanOrEqualTo(root.get("createTime"), params.getCreateTimeStart().atStartOfDay());
                predicates.add(timeStart);
            }
            if (params.getCreateTimeEnd() != null) {
                Predicate timeEnd = criteriaBuilder.lessThan(root.get("createTime"), params.getCreateTimeEnd().plusDays(1).atStartOfDay());
                predicates.add(timeEnd);
            }
            if (params.getActDepartureTimeStart() != null) {
                Predicate timeStart = criteriaBuilder.greaterThanOrEqualTo(root.get("actDepartureTime"), params.getActDepartureTimeStart());
                predicates.add(timeStart);
            }
            if (params.getActDepartureTimeEnd() != null) {
                Predicate timeEnd = criteriaBuilder.lessThan(root.get("actDepartureTime"), params.getActDepartureTimeEnd().plusDays(1));
                predicates.add(timeEnd);
            }
            // 派送日期
            if (params.getReceiveDateStart() != null) {
                Predicate timeStart = criteriaBuilder.greaterThanOrEqualTo(root.get("receiveDate"), params.getReceiveDateStart());
                predicates.add(timeStart);
            }
            if (params.getReceiveDateEnd() != null) {
                Predicate timeEnd = criteriaBuilder.lessThan(root.get("receiveDate"), params.getReceiveDateEnd().plusDays(1));
                predicates.add(timeEnd);
            }
            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        });
        Sort order = new Sort(Sort.Direction.DESC, "createTime", "orderNumber");
        List<GhOrder> ghOrders = ghOrderRepository.findAll(specification, order);
        List<GhOrderDto> dtos = new ArrayList<>();
        List<String> ids = ghOrders.stream().map(GhOrder::getId).collect(Collectors.toList());
        List<ClientVehiclePrice> vehiclePrices = clientVehiclePriceRepository.findByBelongIdIn(ids);
        ghOrders.forEach(ghOrder -> {
            GhOrderDto dto = new GhOrderDto();
            BeanUtils.copyProperties(ghOrder, dto);
            List<ClientVehiclePrice> clientVehiclePrices = vehiclePrices.stream().filter(clientVehiclePrice -> clientVehiclePrice.getBelongId().equals(ghOrder.getId())).collect(Collectors.toList());
            if (clientVehiclePrices.size() > 0) {
                List<ClientVehiclePriceDto> vehiclePriceDtos = new ArrayList<>();
                for (ClientVehiclePrice clientVehiclePrice : clientVehiclePrices) {
                    ClientVehiclePriceDto vehiclePriceDto = new ClientVehiclePriceDto();
                    vehiclePriceDto.setName(clientVehiclePrice.getName());
                    vehiclePriceDto.setAmount(clientVehiclePrice.getAmount());
                    vehiclePriceDtos.add(vehiclePriceDto);
                }
                dto.setVehiclePrices(vehiclePriceDtos);
            }
            dtos.add(dto);
        });
        return dtos;
    }

    @Override
    public void confirmOrder(List<String> ids, String userId) {
        List<GhOrder> ghOrders = ghOrderRepository.findAll(ids);
        User user = userRepository.findById(userId);
        List<LogCreateDto> dtos = new ArrayList<>();
        ghOrders.forEach(order -> {
            order.setStatus(OrderStatus.CONFIRMED);
            LogCreateDto logCreateDto = new LogCreateDto(user.getId(), user.getNickName(), "锁定综合物流", order.getOrderNumber());
            dtos.add(logCreateDto);
        });
        ghOrderRepository.save(ghOrders);
        dtos.forEach(logService::create);
    }

    @Override
    public void unConfirmOrder(List<String> ids, String userId) {
        List<GhOrder> ghOrders = ghOrderRepository.findAll(ids);
        User user = userRepository.findById(userId);
        List<LogCreateDto> dtos = new ArrayList<>();
        ghOrders.forEach(order -> {
            order.setStatus(OrderStatus.UN_CONFIRM);
            LogCreateDto logCreateDto = new LogCreateDto(user.getId(), user.getNickName(), "解锁综合物流", order.getOrderNumber());
            dtos.add(logCreateDto);
        });
        ghOrderRepository.save(ghOrders);
        dtos.forEach(logService::create);
    }

    @Override
    public List<GhOrderDto> query(String orgId, String selectId, String pickDateStart, String pickDateEnd, String currency, String type, List<ExchangeRate> finalRates, String userId) {
        User user = userRepository.findById(userId);
        Role role = roleRepository.findById(user.getRoleId());
        Specification<GhOrder> specification = ((root, criteriaQuery, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            if (RoleType.SUPER_ADMIN.equals(role.getName())) {
                // 得到所有的订单
                List<String> orgIds = organizationService.getAllOrgIds();
                Expression<String> exp = root.get("organizationId");
                predicates.add(exp.in(orgIds));
                // 组织机构ID
                if (StringUtils.hasText(orgId)) {
                    Predicate organizationId = criteriaBuilder.equal(root.get("organizationId"), orgId);
                    predicates.add(organizationId);
                }
            } else if (RoleType.ADMIN.equals(role.getName())) {
                // 得到当前机构及子机构的所有订单
                List<String> orgIds = organizationService.getChildOrgIds(user.getOrganizationId());
                Expression<String> exp = root.get("organizationId");
                predicates.add(exp.in(orgIds));
                // 组织机构ID
                if (StringUtils.hasText(orgId)) {
                    Predicate organizationId = criteriaBuilder.equal(root.get("organizationId"), orgId);
                    predicates.add(organizationId);
                }
            } else if (role.isEqualAdmin()) {
                // 授予了机构管理员权限
                List<String> orgIds = organizationService.getChildOrgIds(user.getOrganizationId());
                Expression<String> exp = root.get("organizationId");
                predicates.add(exp.in(orgIds));
                // 组织机构ID
                if (StringUtils.hasText(orgId)) {
                    Predicate organizationId = criteriaBuilder.equal(root.get("organizationId"), orgId);
                    predicates.add(organizationId);
                }
            } else {
                // 得到属于用户当前机构的订单
                List<String> orgIds = organizationService.getChildOrgIds(user.getOrganizationId());
                Expression<String> exp = root.get("organizationId");
                predicates.add(exp.in(orgIds));
            }
            if (TypeStringUtils.feeInType.equals(type) && StringUtils.hasText(selectId)) {
                Predicate clientIdEqual = criteriaBuilder.equal(root.get("clientId").as(String.class), selectId);
                predicates.add(clientIdEqual);
            } else if (TypeStringUtils.feeOutType.equals(type) && StringUtils.hasText(selectId)) {
                Carrier carrier = carrierRepository.findById(selectId);
                Predicate carrierId = criteriaBuilder.like(root.get("carrierName").as(String.class), "%" + carrier.getName() + "%");
                predicates.add(carrierId);
            }
            if (StringUtils.hasText(pickDateStart)) {
                Predicate timeStart = criteriaBuilder.greaterThanOrEqualTo(root.get("pickDate"), LocalDate.parse(pickDateStart, dateTimeFormatter));
                predicates.add(timeStart);
            }
            if (StringUtils.hasText(pickDateEnd)) {
                Predicate timeEnd = criteriaBuilder.lessThan(root.get("pickDate"), LocalDate.parse(pickDateStart, dateTimeFormatter).plusDays(1));
                predicates.add(timeEnd);
            }
            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        });
        Sort order = new Sort(Sort.Direction.DESC, "createTime", "orderNumber");
        List<GhOrder> ghOrders = ghOrderRepository.findAll(specification, order);
        List<String> ids = ghOrders.stream().map(GhOrder::getId).collect(Collectors.toList());
        List<OrderFee> fees = orderFeeRepository.findByOrderIdIn(ids);
        Carrier carrier = carrierRepository.findById(selectId);
        List<GhOrderDto> dtos = new ArrayList<>();
        ghOrders.forEach(ghOrder -> {
            GhOrderDto dto = new GhOrderDto();
            BeanUtils.copyProperties(ghOrder, dto);
            List<OrderFee> orderFees = fees.stream().filter(orderFee -> orderFee.getOrderId().equals(ghOrder.getId())).collect(Collectors.toList());
            if (orderFees.size() > 0) {
                List<GhOrderDto.FeeDto> feeDtos = new ArrayList<>();
                List<OrderFee> orderFeeList = orderFees.stream().filter(fee -> fee.getType().equals(type)).collect(Collectors.toList());
                // 如果是应付，只需要过滤出所选的供应商费用即可
                if (TypeStringUtils.feeOutType.equals(type) && StringUtils.hasText(selectId)) {
                    orderFeeList = orderFeeList.stream().filter(fee -> carrier.getName().equals(fee.getCarrierId())).collect(Collectors.toList());
                }
                orderFeeList.forEach(orderFee -> {
                    if (orderFee.getFeeCount() == 0) {
                        return;
                    }
                    // 如果费用锁定了，也不导出
                    if (TypeStringUtils.feeLockStatus.equals(orderFee.getStatus())) {
                        return;
                    }
                    if (type.equals(orderFee.getType())) {
                        GhOrderDto.FeeDto feeDto = new GhOrderDto.FeeDto();
                        BeanUtils.copyProperties(orderFee, feeDto);
                        if (StringUtils.isEmpty(currency) || TypeStringUtils.unTransfer.equals(currency) || currency.equals(feeDto.getCurrency())) {
                            feeDtos.add(feeDto);
                        } else {
                            double value = OrderAnalysisServiceImpl.getValueFromCurrency(finalRates, orderFee.getCurrency(), orderFee.getFeeCount());
                            // 全部转成对应币种
                            feeDto.setCurrency(currency);
                            feeDto.setFeeCount(value);
                            feeDtos.add(feeDto);
                        }
                    }
                });
                dto.setFeeList(feeDtos);
            }
            dtos.add(dto);
        });
        return dtos;
    }

    @Override
    public List<GhOrderDto> query(QueryDto queryDto) {
        GhOrderQueryDto orderQueryDto = new GhOrderQueryDto();
        BeanUtils.copyProperties(queryDto, orderQueryDto);
        List<Carrier> carriers = carrierRepository.findAll();
        List<GhOrderDto> ghOrderDtos = this.queryAll(orderQueryDto);
        List<OrderFee> fees = orderFeeRepository.findByOrderIdIn(ghOrderDtos.stream().map(GhOrderDto::getId).collect(Collectors.toList()));
        ghOrderDtos.forEach(dto -> {
            List<OrderFee> orderFees = fees.stream().filter(orderFee -> orderFee.getOrderId().equals(dto.getId())).collect(Collectors.toList());
            if (orderFees.size() > 0) {
                List<GhOrderDto.FeeDto> feeDtos = new ArrayList<>();
                List<OrderFee> orderFeeList = orderFees.stream().filter(fee -> fee.getType().equals(queryDto.getType())).collect(Collectors.toList());
                // 如果是应付，只需要过滤出所选的供应商费用即可
                if (TypeStringUtils.feeOutType.equals(queryDto.getType()) && StringUtils.hasText(queryDto.getCarrierId())) {
                    Carrier carrier = carriers.stream().filter(ca -> ca.getId().equals(queryDto.getCarrierId())).findFirst().orElse(null);
                    if (carrier != null) {
                        orderFeeList = orderFeeList.stream().filter(fee -> carrier.getName().equals(fee.getCarrierId())).collect(Collectors.toList());
                    }
                }
                orderFeeList.forEach(orderFee -> {
                    // 如果费用锁定了，也不导出
                    if (TypeStringUtils.feeLockStatus.equals(orderFee.getStatus())) {
                        return;
                    }
                    if (queryDto.getType().equals(orderFee.getType())) {
                        GhOrderDto.FeeDto feeDto = new GhOrderDto.FeeDto();
                        BeanUtils.copyProperties(orderFee, feeDto);
                        if (StringUtils.isEmpty(queryDto.getCurrency()) || TypeStringUtils.unTransfer.equals(queryDto.getCurrency()) || queryDto.getCurrency().equals(feeDto.getCurrency())) {
                            feeDtos.add(feeDto);
                        } else {
                            double value = OrderAnalysisServiceImpl.getValueFromCurrency(queryDto.getRateList(), orderFee.getCurrency(), orderFee.getFeeCount());
                            // 全部转成对应币种
                            feeDto.setCurrency(queryDto.getCurrency());
                            feeDto.setFeeCount(value);
                            feeDtos.add(feeDto);
                        }
                    }
                });
                dto.setFeeList(feeDtos);
            }
        });
        return ghOrderDtos;
    }

    @Override
    public List<GhOrderDto> getAllByIds(List<String> ids) {
        Specification<GhOrder> specification = ((root, criteriaQuery, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            Expression<String> exp = root.get("id");
            predicates.add(exp.in(ids));
            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        });
        Sort order = new Sort(Sort.Direction.DESC, "createTime", "orderNumber");
        List<GhOrder> ghOrders = ghOrderRepository.findAll(specification, order);
        List<GhOrderDto> dtos = new ArrayList<>();
        List<ClientVehiclePrice> vehiclePrices = clientVehiclePriceRepository.findByBelongIdIn(ids);
        ghOrders.forEach(ghOrder -> {
            GhOrderDto dto = new GhOrderDto();
            BeanUtils.copyProperties(ghOrder, dto);
            List<ClientVehiclePrice> clientVehiclePrices = vehiclePrices.stream().filter(clientVehiclePrice -> clientVehiclePrice.getBelongId().equals(ghOrder.getId())).collect(Collectors.toList());
            if (clientVehiclePrices.size() > 0) {
                List<ClientVehiclePriceDto> vehiclePriceDtos = new ArrayList<>();
                for (ClientVehiclePrice clientVehiclePrice : clientVehiclePrices) {
                    ClientVehiclePriceDto vehiclePriceDto = new ClientVehiclePriceDto();
                    vehiclePriceDto.setName(clientVehiclePrice.getName());
                    vehiclePriceDto.setAmount(clientVehiclePrice.getAmount());
                    vehiclePriceDtos.add(vehiclePriceDto);
                }
                dto.setVehiclePrices(vehiclePriceDtos);
            }
            dtos.add(dto);
        });
        return dtos;
    }


    public static void main(String[] args) {
        /*List<GhOrder> ghOrders = new ArrayList<>();
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        GhOrder o11 = new GhOrder();
        o11.setPickDate(LocalDate.parse("2021-09-10", dateTimeFormatter));
        ghOrders.add(o11);
        GhOrder o22 = new GhOrder();
        o22.setPickDate(LocalDate.parse("2021-09-14", dateTimeFormatter));
        ghOrders.add(o22);
        // 按照提货时间排序
        ghOrders.sort((o1, o2) -> {
            if (o1.getPickDate().isAfter(o2.getPickDate())) {
                return -1;
            } else if (o1.getPickDate().isBefore(o2.getPickDate())) {
                return 1;
            }
            return 0;
        });
        System.out.println("ok");*/
        String text = "45340.56 ".trim();
        System.out.println(GhOrderServiceImpl.isNumber(text));
        ;
    }

    @Override
    public List<GhOrderDto> getAllByIds(List<String> ids, String type, String currency, List<ExchangeRate> finalRates) {
        Specification<GhOrder> specification = ((root, criteriaQuery, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            Expression<String> exp = root.get("id");
            predicates.add(exp.in(ids));
            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        });
        Sort order = new Sort(Sort.Direction.DESC, "createTime", "orderNumber");
        List<GhOrder> ghOrders = ghOrderRepository.findAll(specification, order);
        List<OrderFee> fees = orderFeeRepository.findByOrderIdIn(ids);
        List<GhOrderDto> dtos = new ArrayList<>();
        ghOrders.forEach(ghOrder -> {
            GhOrderDto dto = new GhOrderDto();
            BeanUtils.copyProperties(ghOrder, dto);
            List<OrderFee> orderFees = fees.stream().filter(orderFee -> orderFee.getOrderId().equals(ghOrder.getId())).collect(Collectors.toList());
            if (orderFees.size() > 0) {
                List<GhOrderDto.FeeDto> feeDtos = new ArrayList<>();
                orderFees.forEach(orderFee -> {
                    // 如果费用锁定了，也不导出
                    if (TypeStringUtils.feeLockStatus.equals(orderFee.getStatus())) {
                        return;
                    }
                    if (type.equals(orderFee.getType())) {
                        GhOrderDto.FeeDto feeDto = new GhOrderDto.FeeDto();
                        BeanUtils.copyProperties(orderFee, feeDto);
                        if (StringUtils.isEmpty(currency) || TypeStringUtils.unTransfer.equals(currency) || currency.equals(feeDto.getCurrency())) {
                            feeDtos.add(feeDto);
                        } else {
                            double value = OrderAnalysisServiceImpl.getValueFromCurrency(finalRates, orderFee.getCurrency(), orderFee.getFeeCount());
                            feeDto.setFeeCount(value);
                            feeDtos.add(feeDto);
                        }
                    }
                });
                dto.setFeeList(feeDtos);
            }
            dtos.add(dto);
        });
        return dtos;
    }

    @Override
    public void lockFee(List<String> ids, Set<String> lockColumns) {
        List<OrderFee> orderFees = orderFeeRepository.findByOrderIdIn(ids);
        orderFees.forEach(orderFee -> {
            if (lockColumns.contains(orderFee.getFeeName())) {
                orderFee.setStatus(TypeStringUtils.feeLockStatus);
            }
        });
        orderFeeRepository.save(orderFees);
    }


    @Override
    public void changeInvoice(List<String> orderIds, String type, String opId, String remark) {
        List<GhOrder> ghOrders = ghOrderRepository.findAll(orderIds);
        User op = userRepository.findById(opId);
        for (GhOrder ghOrder : ghOrders) {
            if (TypeStringUtils.feeInType.equals(type)) {
                ghOrder.setInvoice("已开票");
                LogCreateDto logCreateDto = new LogCreateDto(op.getId(), op.getNickName(), "综合物流应收已开票", ghOrder.getOrderNumber());
                logService.create(logCreateDto);
            } else {
                ghOrder.setOutInvoice("已开票");
                LogCreateDto logCreateDto = new LogCreateDto(op.getId(), op.getNickName(), "综合物流应付已开票", ghOrder.getOrderNumber());
                logService.create(logCreateDto);
            }
            ghOrder.setRemark(remark);
            ghOrder.checkCanLock();
            ghOrderRepository.save(ghOrder);
        }
    }

    @Override
    public void changeSettlement(List<String> orderIds, String type, String opId, String remark) {
        List<GhOrder> ghOrders = ghOrderRepository.findAll(orderIds);
        User op = userRepository.findById(opId);
        for (GhOrder ghOrder : ghOrders) {
            ghOrder.setSettlement("已结算");
            LogCreateDto logCreateDto = new LogCreateDto(op.getId(), op.getNickName(), "综合物流应收已结算", ghOrder.getOrderNumber());
            logService.create(logCreateDto);
            // 把所有应收的费用锁定
            List<OrderFee> fees = orderFeeRepository.findByOrderIdAndType(ghOrder.getId(), TypeStringUtils.feeInType);
            for (OrderFee fee : fees) {
                fee.setStatus(TypeStringUtils.feeLockStatus);
            }
            orderFeeRepository.save(fees);
            ghOrder.setOutSettlement("已结算");
            logCreateDto = new LogCreateDto(op.getId(), op.getNickName(), "综合物流应付已结算", ghOrder.getOrderNumber());
            logService.create(logCreateDto);
            // 把所有应付的费用锁定
            fees = orderFeeRepository.findByOrderIdAndType(ghOrder.getId(), TypeStringUtils.feeOutType);
            for (OrderFee fee : fees) {
                fee.setStatus(TypeStringUtils.feeLockStatus);
            }
            orderFeeRepository.save(fees);
            ghOrder.setRemark(remark);
            ghOrder.checkCanLock();
            ghOrderRepository.save(ghOrder);
        }
    }

    @Override
    public void invoiceOrder(OperateOrderDto operateOrderDto) {
        ExportLog exportLog = exportLogRepository.findFirstById(operateOrderDto.getLogId());
        if (operateOrderDto.getInvoiceDate() != null) {
            exportLog.setInvoiceDate(operateOrderDto.getInvoiceDate());
        }
        if (operateOrderDto.getSettlementDate() != null) {
            exportLog.setSettlementDate(operateOrderDto.getSettlementDate());
        }
        exportLog.setSettlementDate(operateOrderDto.getSettlementDate());
        if (StringUtils.hasText(operateOrderDto.getRemark())) {
            String text = StringUtils.isEmpty(exportLog.getRemark()) ? "" : exportLog.getRemark() + ";";
            exportLog.setRemark(text + operateOrderDto.getRemark());
        }
        exportLogRepository.save(exportLog);
        String ids = exportLog.getIds();
        if (ids != null) {
            String[] idsArray = ids.split(",");
            this.changeInvoice(Arrays.asList(idsArray), operateOrderDto.getType(), operateOrderDto.getOpId(), operateOrderDto.getRemark());
        }
    }

    @Override
    public void settlementOrder(OperateOrderDto operateOrderDto) {
        ExportLog exportLog = exportLogRepository.findFirstById(operateOrderDto.getLogId());
        if (operateOrderDto.getInvoiceDate() != null) {
            exportLog.setInvoiceDate(operateOrderDto.getInvoiceDate());
        }
        if (operateOrderDto.getSettlementDate() != null) {
            exportLog.setSettlementDate(operateOrderDto.getSettlementDate());
        }
        exportLog.setSettlementDate(operateOrderDto.getSettlementDate());
        if (StringUtils.hasText(operateOrderDto.getRemark())) {
            String text = StringUtils.isEmpty(exportLog.getRemark()) ? "" : exportLog.getRemark() + ";";
            exportLog.setRemark(text + operateOrderDto.getRemark());
        }
        exportLogRepository.save(exportLog);
        String ids = exportLog.getIds();
        if (ids != null) {
            String[] idsArray = ids.split(",");
            this.changeSettlement(Arrays.asList(idsArray), operateOrderDto.getType(), operateOrderDto.getOpId(), operateOrderDto.getRemark());
        }
    }

    @Override
    public Result<?> batchCreate(List<GhOrderImportDto> importDatas, String opId) {
        User user = userRepository.findById(opId);
        List<Organization> organizations = organizationService.getAll();
        List<Client> clients = clientRepository.findAll();
        List<LinePrice> linePrices = linePriceRepository.findAll();
        // 校验错误的消息列表
        List<String> messageList = new ArrayList<>();
        // 每一行检查的报错信息列表
        List<String> lineErrorList;
        // 允许导入的数据
        List<GhOrderImportDto> canImportDtos = new ArrayList<>();
        int currentIndex = 1;
        // 如果有填订单编号，则需要更新
        List<GhOrder> ghOrdersByOrderNos = ghOrderRepository.findAllByOrderNumberIn(importDatas.stream().filter(o -> StringUtils.hasText(o.getOrderNumber())).map(GhOrderImportDto::getOrderNumber).collect(Collectors.toList()));
        for (GhOrderImportDto importData : importDatas) {
            lineErrorList = new ArrayList<>();
            if (StringUtils.isEmpty(importData.getOrganizationName())) {
                lineErrorList.add(String.format("第【%s】行数据，机构抬头不能为空", currentIndex));
            } else {
                boolean anyMatch = organizations.stream().anyMatch(organization -> organization.getName().equals(importData.getOrganizationName()));
                if (!anyMatch) {
                    lineErrorList.add(String.format("第【%s】行数据，没有找到机构抬头为【%s】的记录", currentIndex, importData.getOrganizationName()));
                }
            }
            if (StringUtils.isEmpty(importData.getClientName())) {
                lineErrorList.add(String.format("第【%s】行数据，客户简称不能为空", currentIndex));
            } else {
                // 再判断当前所选机构是否有此客户
                Optional<Organization> optional = organizations.stream().filter(organization -> organization.getName().equals(importData.getOrganizationName())).findFirst();
                if (optional.isPresent()) {
                    Organization organization = optional.get();
                    List<Client> filterClients = clients.stream().filter(client -> client.getOrganizationId().equals(organization.getId())).collect(Collectors.toList());
                    boolean anyMatch = filterClients.stream().anyMatch(client -> client.getName().equals(importData.getClientName()));
                    if (!anyMatch) {
                        lineErrorList.add(String.format("第【%s】行数据，在机构【%s】下找不到客户简称为【%s】的客户", currentIndex, organization.getName(), importData.getClientName()));
                    }
                }
            }
            if (StringUtils.isEmpty(importData.getPickDate())) {
                lineErrorList.add(String.format("第【%s】行数据，提货日期必填", currentIndex));
            }
            if (StringUtils.isEmpty(importData.getCalculateType())) {
                lineErrorList.add(String.format("第【%s】行数据，计费方式必填", currentIndex));
            } else {
                CalculateType calculateType = CalculateTypeUtil.getCalculateType(importData.getCalculateType());
                if (calculateType == null) {
                    lineErrorList.add(String.format("第【%s】行数据，系统不存在此计费方式【%s】", currentIndex, importData.getCalculateType()));
                } else {
                    // 按照数量计费，但是数量没值
                    if (calculateType.equals(CalculateType.QUANTITY) && StringUtils.isEmpty(importData.getQuantity())) {
                        lineErrorList.add(String.format("第【%s】行数据，计费方式为数量，但【数量】一列没有数据", currentIndex));
                    } else if (calculateType.equals(CalculateType.VOLUME) && StringUtils.isEmpty(importData.getSquareNumber())) {
                        lineErrorList.add(String.format("第【%s】行数据，计费方式为体积，但【方数(m³)】一列没有数据", currentIndex));
                    } else if (calculateType.equals(CalculateType.WEIGHT) && StringUtils.isEmpty(importData.getSquareNumber())) {
                        lineErrorList.add(String.format("第【%s】行数据，计费方式为重量，但【毛重(KG)】一列没有数据", currentIndex));
                    }
                }
            }
            if (StringUtils.isEmpty(importData.getBusinessCode())) {
                lineErrorList.add(String.format("第【%s】行数据，业务类型必填", currentIndex));
            }
            if (StringUtils.isEmpty(importData.getBookNumber())) {
                lineErrorList.add(String.format("第【%s】行数据，订舱号必填", currentIndex));
            }
            if (StringUtils.hasText(importData.getOriginDestPlace())) {
                String[] strings = importData.getOriginDestPlace().split("-");
                importData.setOriginPlace(strings[0].trim());
                importData.setDestPlace(strings[strings.length - 1].trim());
            }
            // 去除字符串两边的空格
            if (importData.getOriginDestPlace() != null) {
                importData.setOriginDestPlace(importData.getOriginDestPlace().trim());
            }
            if (importData.getVehicleLine() != null) {
                importData.setVehicleLine(importData.getVehicleLine().trim());
            }
            if (importData.getDeliveryLine() != null) {
                importData.setDeliveryLine(importData.getDeliveryLine().trim());
            }
            if (lineErrorList.size() == 0) {
                canImportDtos.add(importData);
            } else {
                messageList.add(String.join(";", lineErrorList));
            }
            importData.setIndex(currentIndex);
            currentIndex++;
        }
        if (messageList.size() > 0) {
            return Result.success(messageList);
        }
        for (GhOrderImportDto importData : canImportDtos) {
            GhOrderCreateDto createDto = new GhOrderCreateDto();
            if (importData.getQuantity() == null) {
                importData.setQuantity(0);
            }
            if (importData.getSquareNumber() == null) {
                importData.setSquareNumber(0d);
            }
            if (importData.getVolumeWeight() == null) {
                importData.setVolumeWeight(0d);
            }
            if (importData.getGrossWeight() == null) {
                importData.setGrossWeight(0d);
            }
            // 泡比
            if (StringUtils.hasText(importData.getPb())) {
                try {
                    String pb = importData.getPb().replace("：", ":");
                    if (pb.contains(":")) {
                        createDto.setPb(new Double(pb.split(":")[1]));
                    } else {
                        createDto.setPb(new Double(pb));
                    }
                } catch (Exception ignored) {
                }
            }
            // 如果有订单编号，则覆盖原数据
            if (StringUtils.hasText(importData.getOrderNumber())) {
                // 订单编号、机构、客户、订舱号、业务类型相同时，其他部分直接覆盖
                Optional<GhOrder> optionalGhOrder = ghOrdersByOrderNos.stream().filter(order -> order.getOrderNumber().equals(importData.getOrderNumber()) && order.getOrganizationName().equals(importData.getOrganizationName()) && order.getClientName().equals(importData.getClientName()) && StringUtils.hasText(order.getBookNumber()) && order.getBookNumber().equals(importData.getBookNumber()) && StringUtils.hasText(order.getBusinessCode()) && order.getBusinessCode().equals(importData.getBusinessCode())).findFirst();
                if (optionalGhOrder.isPresent()) {
                    // 通过订舱号查找记录
                    GhOrder ghOrder = optionalGhOrder.get();
                    // 如果是锁账了，则不允许修改
                    if (BillType.STATUS_YJS.equals(ghOrder.getSettlement()) || BillType.STATUS_YJS.equals(ghOrder.getOutSettlement())) {
                        messageList.add(String.format("订单编号为【%s】已锁账，不允许编辑", ghOrder.getOrderNumber()));
                        continue;
                    }
                    BeanUtils.copyProperties(importData, ghOrder, "id", "orderNumber", "organizationId", "clientId", "bookNumber", "businessCode");
                    // 重新计算费用
                    CalculateDto calculateDto = new CalculateDto();
                    BeanUtils.copyProperties(ghOrder, calculateDto);
                    calculateDto.setCalculateType(CalculateTypeUtil.getCalculateType(ghOrder.getCalculateType()));
                    calculateDto.setCalculateTime(ghOrder.getPickDate());
                    calculateDto.setGhOrder(true);
                    calculateDto.setNoTips(true);
                    List<PriceDto> priceDtos = calculateService.calculate(calculateDto);
                    // 删除旧的应收费用记录
                    orderFeeRepository.deleteByOrderIdAndType(ghOrder.getId(), TypeStringUtils.feeInType);
                    // 保存应收费用
                    List<OrderFee> orderFees = new ArrayList<>();
                    for (PriceDto priceDto : priceDtos) {
                        OrderFee fee = new OrderFee();
                        BeanUtils.copyProperties(priceDto, fee);
                        fee.setId(snowFlakeFactory.nextId("OF"));
                        fee.setOrderId(ghOrder.getId());
                        // 系统发车时间为准，后面方便于统计应付费用
                        if (ghOrder.getActDepartureTime() != null) {
                            fee.setCreateTime(ghOrder.getActDepartureTime().atStartOfDay());
                        }
                        fee.setType(TypeStringUtils.feeInType);
                        orderFees.add(fee);
                    }
                    // 重新计算应付费用记录
                    List<OrderFee> outFees = orderFeeRepository.findByOrderIdAndType(ghOrder.getId(), TypeStringUtils.feeOutType);
                    for (OrderFee outFee : outFees) {
                        calculateDto = new CalculateDto();
                        BeanUtils.copyProperties(ghOrder, calculateDto);
                        calculateDto.setCarrierId(outFee.getCarrierId());
                        calculateDto.setCalculateType(CalculateTypeUtil.getCalculateType(ghOrder.getCalculateType()));
                        calculateDto.setCalculateTime(ghOrder.getPickDate());
                        calculateDto.setGhOrder(true);
                        calculateDto.setNoTips(true);
                        priceDtos = calculateService.calculateOut(calculateDto);
                        for (PriceDto priceDto : priceDtos) {
                            OrderFee fee = new OrderFee();
                            BeanUtils.copyProperties(priceDto, fee);
                            fee.setId(snowFlakeFactory.nextId("OF"));
                            fee.setOrderId(ghOrder.getId());
                            // 系统发车时间为准，后面方便于统计应付费用
                            if (ghOrder.getActDepartureTime() != null) {
                                fee.setCreateTime(ghOrder.getActDepartureTime().atStartOfDay());
                            }
                            fee.setType(TypeStringUtils.feeOutType);
                            fee.setCarrierId(outFee.getCarrierId());
                            orderFees.add(fee);
                        }
                    }
                    orderFeeRepository.save(orderFees);
                    // 保存
                    ghOrderRepository.save(ghOrder);
                    continue;
                } else {
                    // 导入时订单编号一样，机构、客户、订舱号不一样时，弹窗提示同一机构下“订舱号”重复
                    boolean hasRecord = ghOrdersByOrderNos.stream().anyMatch(order -> !order.getOrderNumber().equals(importData.getOrderNumber()) && order.getOrganizationName().equals(importData.getOrganizationName()) && order.getClientName().equals(importData.getClientName()) && StringUtils.hasText(order.getBookNumber()) && order.getBookNumber().equals(importData.getBookNumber()));
                    if (hasRecord) {
                        messageList.add(String.format("同一机构下【%s】订舱号【%s】重复", importData.getOrganizationName(), importData.getBookNumber()));
                        continue;
                    }
                }
            } else {
                // 机构、客户、订舱号、业务类型相同时，弹窗提示同一机构下“订舱号”重复
                long count = ghOrderRepository.countByOrganizationNameAndClientNameAndBookNumberAndBusinessCode(importData.getOrganizationName(), importData.getClientName(), importData.getBookNumber(), importData.getBusinessCode());
                if (count > 0) {
                    messageList.add(String.format("同一机构下【%s】订舱号【%s】重复", importData.getOrganizationName(), importData.getBookNumber()));
                    continue;
                }
            }
            BeanUtils.copyProperties(importData, createDto);
            if (StringUtils.hasText(importData.getPickDate())) {
                Instant instant = DateUtils.parseDate(importData.getPickDate()).toInstant();
                ZoneId zoneId = ZoneId.systemDefault();
                // atZone()方法返回在指定时区从此Instant生成的ZonedDateTime
                createDto.setPickDate(instant.atZone(zoneId).toLocalDate());
            }
            if (StringUtils.hasText(importData.getActDepartureTime())) {
                Instant instant = DateUtils.parseDate(importData.getActDepartureTime()).toInstant();
                ZoneId zoneId = ZoneId.systemDefault();
                // atZone()方法返回在指定时区从此Instant生成的ZonedDateTime
                createDto.setActDepartureTime(instant.atZone(zoneId).toLocalDate());
            }
            if (StringUtils.hasText(importData.getCalculateType())) {
                CalculateType calculateType = CalculateTypeUtil.getCalculateType(importData.getCalculateType());
                if (calculateType != null) {
                    createDto.setCalculateType(calculateType.name());
                }
            }
            if (StringUtils.hasText(importData.getReceiveDate())) {
                Instant instant = DateUtils.parseDate(importData.getReceiveDate()).toInstant();
                ZoneId zoneId = ZoneId.systemDefault();
                // atZone()方法返回在指定时区从此Instant生成的ZonedDateTime
                createDto.setReceiveDate(instant.atZone(zoneId).toLocalDate());
            }
            organizations.stream().filter(organization -> organization.getName().equals(importData.getOrganizationName())).findFirst().ifPresent(organization -> createDto.setOrganizationId(organization.getId()));
            if (StringUtils.isEmpty(createDto.getOrganizationId())) {
                createDto.setOrganizationId(user.getOrganizationId());
            }
            clients.stream().filter(client -> client.getOrganizationId().equals(createDto.getOrganizationId())).collect(Collectors.toList()).stream().filter(client -> client.getName().equals(importData.getClientName())).findFirst().ifPresent(client -> createDto.setClientId(client.getId()));
            createDto.setOpId(opId);
            // 泡比
            linePrices.stream().filter(linePrice -> linePrice.getBelongId().equals(createDto.getClientId())).collect(Collectors.toList()).stream().filter(linePrice -> linePrice.getOriginPlace().equals(createDto.getOriginPlace()) && linePrice.getDestPlace().equals(createDto.getDestPlace())).findFirst().ifPresent(linePrice -> createDto.setPb(linePrice.getPb()));
            // 算费用
            CalculateDto calculateDto = new CalculateDto();
            BeanUtils.copyProperties(createDto, calculateDto);
            calculateDto.setCalculateType(CalculateTypeUtil.getCalculateType(importData.getCalculateType()));
            createDto.setCalculateType(calculateDto.getCalculateType().name());
            calculateDto.setCalculateTime(createDto.getPickDate());
            calculateDto.setGhOrder(true);
            List<PriceDto> priceDtos = calculateService.calculate(calculateDto);
            if (priceDtos != null && priceDtos.size() > 0) {
                List<GhOrderCreateDto.FeeDto> feeDtos = new ArrayList<>();
                for (PriceDto priceDto : priceDtos) {
                    GhOrderCreateDto.FeeDto feeDto = new GhOrderCreateDto.FeeDto();
                    BeanUtils.copyProperties(priceDto, feeDto);
                    feeDtos.add(feeDto);
                }
                createDto.setFeeList(feeDtos);
            }
            // 生成提货费、派送费
            /*Client client = clients.stream().filter(c -> c.getName().equals(importData.getClientName()))
                    .findFirst().orElse(null);
            if (client != null) {
                List<ClientVehiclePrice> clientVehiclePrices = vehiclePrices.stream().filter(clientVehiclePrice -> clientVehiclePrice.getBelongId().equals(client.getId())).collect(Collectors.toList());
                clientVehiclePrices.stream().filter(clientVehiclePrice -> clientVehiclePrice.getName().equals(importData.getVehicleType()) &&
                        StringUtils.hasText(importData.getVehicleLine()) &&
                        StringUtils.hasText(clientVehiclePrice.getStartPlace()) &&
                        StringUtils.hasText(clientVehiclePrice.getEndPlace()) &&
                        importData.getVehicleLine().startsWith(clientVehiclePrice.getStartPlace()) &&
                        importData.getVehicleLine().endsWith(clientVehiclePrice.getEndPlace()))
                        .findFirst()
                        .ifPresent(clientVehiclePrice -> {
                            ClientVehiclePriceDto dto = new ClientVehiclePriceDto();
                            BeanUtils.copyProperties(clientVehiclePrice, dto);
                            createDto.getVehiclePrices().add(dto);
                            if (createDto.getFeeList() == null) {
                                createDto.setFeeList(new ArrayList<>());
                            }
                            GhOrderCreateDto.FeeDto feeDto = new GhOrderCreateDto.FeeDto();
                            feeDto.setCurrency(TypeStringUtils.RMB);
                            feeDto.setFeeCount(clientVehiclePrice.getAmount());
                            feeDto.setFeeName(FeeNameStringUtils.PICKUP_FEE);
                            createDto.getFeeList().add(feeDto);
                        });
                clientVehiclePrices.stream().filter(clientVehiclePrice -> StringUtils.hasText(importData.getDeliveryLine()) &&
                        clientVehiclePrice.getName().equals(importData.getVehicleType()) &&
                        StringUtils.hasText(clientVehiclePrice.getStartPlace()) &&
                        StringUtils.hasText(clientVehiclePrice.getEndPlace()) &&
                        importData.getDeliveryLine().startsWith(clientVehiclePrice.getStartPlace()) &&
                        importData.getDeliveryLine().endsWith(clientVehiclePrice.getEndPlace()))
                        .findFirst()
                        .ifPresent(clientVehiclePrice -> {
                            ClientVehiclePriceDto dto = new ClientVehiclePriceDto();
                            BeanUtils.copyProperties(clientVehiclePrice, dto);
                            createDto.getVehiclePrices().add(dto);
                            if (createDto.getFeeList() == null) {
                                createDto.setFeeList(new ArrayList<>());
                            }
                            GhOrderCreateDto.FeeDto feeDto = new GhOrderCreateDto.FeeDto();
                            feeDto.setCurrency(TypeStringUtils.RMB);
                            feeDto.setFeeCount(clientVehiclePrice.getAmount());
                            feeDto.setFeeName(FeeNameStringUtils.DELIVERY_FEE);
                            createDto.getFeeList().add(feeDto);
                        });
            }*/
            try {
                this.create(createDto);
            } catch (Exception e) {
                messageList.add(String.format("表格第【%s】行录入失败【%s】", importData.getIndex(), e.getMessage()));
            }
        }
        return Result.success(messageList);
    }

    @Override
    public void reCalculateFee(List<String> ids) {
        List<GhOrder> ghOrders = ghOrderRepository.findAll(ids);
        List<OrderFee> orderFees = orderFeeRepository.findByOrderIdIn(ids);
        CalculateDto calculateDto;
        for (GhOrder ghOrder : ghOrders) {
            calculateDto = new CalculateDto();
            BeanUtils.copyProperties(ghOrder, calculateDto);
            calculateDto.setCalculateType(CalculateTypeUtil.getCalculateType(ghOrder.getCalculateType()));
            calculateDto.setNoTips(true);
            // 重新计算应收费用
            calculateDto.setGhOrder(true);
            List<PriceDto> inPriceList = calculateService.calculate(calculateDto);
            List<OrderFee> oFees = orderFees.stream().filter(orderFee -> orderFee.getOrderId().equals(ghOrder.getId())).collect(Collectors.toList());
            for (OrderFee oFee : oFees) {
                // 如果费用为0
                if (oFee.getFeeCount() == 0) {
                    // 判断费用类型
                    if (TypeStringUtils.feeInType.equals(oFee.getType()) && inPriceList != null && inPriceList.size() > 0) {
                        inPriceList.stream().filter(price -> price.getFeeName().equals(oFee.getFeeName())).findFirst().ifPresent(price -> {
                            oFee.setFeeCount(price.getFeeCount());
                            oFee.setCurrency(price.getCurrency());
                        });
                    } else if (TypeStringUtils.feeOutType.equals(oFee.getType())) {
                        // 先判断供应商是否不为空
                        if (StringUtils.hasText(oFee.getCarrierId())) {
                            calculateDto.setCarrierId(oFee.getCarrierId());
                            calculateDto.setFeeName(oFee.getFeeName());
                            List<PriceDto> outPriceList = calculateService.calculateOut(calculateDto);
                            if (outPriceList != null && outPriceList.size() > 0) {
                                oFee.setFeeCount(outPriceList.get(0).getFeeCount());
                                oFee.setCurrency(outPriceList.get(0).getCurrency());
                            }
                        }
                    }
                }
            }
            orderFeeRepository.save(oFees);
        }
    }

    @Override
    public void reCalculateFeeById(ReCalculateFeeParams params) {
        List<OrderFee> orderFees = orderFeeRepository.findByOrderId(params.getId());
        CalculateDto calculateDto = new CalculateDto();
        BeanUtils.copyProperties(params.getGhOrderDto(), calculateDto);
        calculateDto.setCalculateType(CalculateTypeUtil.getCalculateType(params.getGhOrderDto().getCalculateType()));
        // 前端是否提示标志
        calculateDto.setNoTips(true);
        // 综合物流标志
        calculateDto.setGhOrder(true);
        // 综合物流按照提货日期计算费用
        calculateDto.setCalculateTime(params.getGhOrderDto().getPickDate());
        // 重新计算应收费用
        List<PriceDto> inPriceList = calculateService.calculate(calculateDto);
        for (OrderFee oFee : orderFees) {
            if (!oFee.getFeeName().equals(params.getFeeName())) continue;
            // 判断费用类型
            if (TypeStringUtils.feeInType.equals(oFee.getType()) && inPriceList != null && inPriceList.size() > 0) {
                inPriceList.stream().filter(price -> price.getFeeName().equals(oFee.getFeeName())).findFirst().ifPresent(price -> {
                    oFee.setFeeCount(price.getFeeCount());
                    oFee.setCurrency(price.getCurrency());
                });
            } else if (TypeStringUtils.feeOutType.equals(oFee.getType())) {
                // 先判断供应商是否不为空
                if (StringUtils.hasText(oFee.getCarrierId())) {
                    calculateDto.setCarrierId(oFee.getCarrierId());
                    calculateDto.setFeeName(oFee.getFeeName());
                    List<PriceDto> outPriceList = calculateService.calculateOut(calculateDto);
                    if (outPriceList != null && outPriceList.size() > 0) {
                        oFee.setFeeCount(outPriceList.get(0).getFeeCount());
                        oFee.setCurrency(outPriceList.get(0).getCurrency());
                    }
                }
            }
        }
        orderFeeRepository.save(orderFees);
    }

    @Override
    public GhOrderDto getById(String id) {
        GhOrder ghOrder = ghOrderRepository.findById(id);
        GhOrderDto dto = new GhOrderDto();
        BeanUtils.copyProperties(ghOrder, dto);
        BaoGuanFee guanFee = baoGuanFeeRepository.findByBelongId(id);
        List<OrderFee> fees = orderFeeRepository.findByOrderId(id);
        List<ClientVehiclePrice> vehiclePrices = clientVehiclePriceRepository.findByBelongId(id);
        if (guanFee != null) {
            dto.setHomeFee(guanFee.getHomeFee());
            dto.setHomeCount(guanFee.getHomeCount());
            dto.setSheetFee(guanFee.getSheetFee());
            dto.setSheetCount(guanFee.getSheetCount());
        }
        List<OrderFee> orderFees = fees.stream().filter(orderFee -> orderFee.getOrderId().equals(ghOrder.getId())).collect(Collectors.toList());
        if (orderFees.size() > 0) {
            List<GhOrderDto.FeeDto> feeDtos = new ArrayList<>();
            List<GhOrderDto.FeeDto> outFeeDtos = new ArrayList<>();
            orderFees.forEach(orderFee -> {
                GhOrderDto.FeeDto feeDto = new GhOrderDto.FeeDto();
                BeanUtils.copyProperties(orderFee, feeDto);
                if (TypeStringUtils.feeInType.equals(orderFee.getType())) {
                    feeDtos.add(feeDto);
                } else {
                    outFeeDtos.add(feeDto);
                }
            });
            dto.setFeeList(feeDtos);
            dto.setOutFeeList(outFeeDtos);
        }
        List<ClientVehiclePrice> clientVehiclePrices = vehiclePrices.stream().filter(clientVehiclePrice -> clientVehiclePrice.getBelongId().equals(ghOrder.getId())).collect(Collectors.toList());
        if (clientVehiclePrices.size() > 0) {
            List<ClientVehiclePriceDto> vehiclePriceDtos = new ArrayList<>();
            for (ClientVehiclePrice clientVehiclePrice : clientVehiclePrices) {
                ClientVehiclePriceDto vehiclePriceDto = new ClientVehiclePriceDto();
                vehiclePriceDto.setName(clientVehiclePrice.getName());
                vehiclePriceDto.setAmount(clientVehiclePrice.getAmount());
                vehiclePriceDtos.add(vehiclePriceDto);
            }
            dto.setVehiclePrices(vehiclePriceDtos);
        }
        return dto;
    }

    @Override
    public List<OrderFee> getFeeListById(String id) {
        return orderFeeRepository.findByOrderId(id);
    }

    @Override
    public List<OrderFee> getFeeListByIdIn(List<String> ids) {
        return orderFeeRepository.findByOrderIdIn(ids);
    }

    @Override
    public Set<String> batchCreateInFee(List<Map<String, String>> dataList) {
        // 获取系统配置的币种列表
        List<ExchangeRate> exchangeRates = rateRepository.findAll();
        List<String> currencyList = new ArrayList<>();
        for (ExchangeRate exchangeRate : exchangeRates) {
            if (!currencyList.contains(exchangeRate.getFromRate())) {
                currencyList.add(exchangeRate.getFromRate());
            }
            if (!currencyList.contains(exchangeRate.getToRate())) {
                currencyList.add(exchangeRate.getToRate());
            }
        }
        Set<String> messageList = new HashSet<>();
        // 取出所有的订单号
        List<String> orderNumberList = new ArrayList<>();
        for (Map<String, String> stringStringMap : dataList) {
            String orderNumber = stringStringMap.get("订单编号");
            if (StringUtils.hasText(orderNumber)) {
                orderNumberList.add(orderNumber);
            }
        }
        List<GhOrder> ghOrders = ghOrderRepository.findAllByOrderNumberIn(orderNumberList);
        // 已经锁定的账单
        List<GhOrder> lockOrders = ghOrders.stream().filter(ghOrder -> BillType.STATUS_YJS.equals(ghOrder.getSettlement()) || BillType.STATUS_YJS.equals(ghOrder.getOutSettlement())).collect(Collectors.toList());
        if (lockOrders.size() > 0) {
            for (GhOrder lockOrder : lockOrders) {
                messageList.add(String.format("订单编号【%s】已封账，无法导入应收费用", lockOrder.getOrderNumber()));
            }
        }
        if (messageList.size() > 0) {
            return messageList;
        }
        int index = 1;
        for (Map<String, String> stringStringMap : dataList) {
            String orderNumber = stringStringMap.get("订单编号");
            if (StringUtils.hasText(orderNumber) && !orderNumber.toLowerCase().contains("null")) {
                boolean anyMatch = ghOrders.stream().anyMatch(order -> order.getOrderNumber().equals(orderNumber));
                if (!anyMatch) {
                    messageList.add(String.format("【应收】第【%d】行根据订单编号【%s】在系统找不到记录", index, orderNumber));
                }
            }
            index++;
            int finalIndex = index;
            ghOrders.stream().filter(ghOrder -> ghOrder.getOrderNumber().equals(orderNumber)).findFirst().ifPresent(ghOrder -> {
                // 查出所有的费用
                List<OrderFee> orderFees = orderFeeRepository.findByOrderIdAndType(ghOrder.getId(), TypeStringUtils.feeInType);
                // 判断之前是否已经生成了运输费，如果没有，需要生成运输费
                OrderFee existRecord = orderFees.stream().filter(orderFee -> TypeStringUtils.feeInType.equals(orderFee.getType()) && TypeStringUtils.TRANSPORT_FEE.equals(orderFee.getFeeName())).findFirst().orElse(null);
                if (existRecord == null) {
                    existRecord = new OrderFee();
                    existRecord.setId(snowFlakeFactory.nextId("OF"));
                    existRecord.setOrderId(ghOrder.getId());
                    existRecord.setFeeName(TypeStringUtils.TRANSPORT_FEE);
                    existRecord.setCreateTime(ghOrder.getActDepartureTime().atStartOfDay());
                    existRecord.setType(TypeStringUtils.feeInType);
                }
                // // 如果没有填入运输费，则自动计算
                if (StringUtils.hasText(stringStringMap.get(TypeStringUtils.TRANSPORT_FEE))) {
                    existRecord.setCurrency(getCurrencyV2(stringStringMap.get(TypeStringUtils.TRANSPORT_FEE + "币种"), currencyList));
                    try {
                        existRecord.setFeeCount(new Double(stringStringMap.get(TypeStringUtils.TRANSPORT_FEE)));
                    } catch (Exception e) {
                        messageList.add(String.format("【应收】第【%d】行转换运输费【%s】失败，请检查", finalIndex, stringStringMap.get(TypeStringUtils.TRANSPORT_FEE)));
                    }
                } else {
                    // 自动生成运输费
                    CalculateDto calculateDto = new CalculateDto();
                    BeanUtils.copyProperties(ghOrder, calculateDto);
                    calculateDto.setGhOrder(true);
                    // 计费方式按照提货日期
                    calculateDto.setCalculateTime(ghOrder.getPickDate());
                    calculateDto.setCalculateType(CalculateTypeUtil.getCalculateType(ghOrder.getCalculateType()));
                    List<PriceDto> priceDtos = calculateService.calculate(calculateDto);
                    Optional<PriceDto> first = priceDtos.stream().filter(priceDto -> priceDto.getFeeName().equals(TypeStringUtils.TRANSPORT_FEE)).findFirst();
                    if (first.isPresent()) {
                        existRecord.setCurrency(first.get().getCurrency());
                        existRecord.setFeeCount(first.get().getFeeCount());
                    }
                }
                if (messageList.size() == 0) {
                    orderFeeRepository.save(existRecord);
                }
                // 遍历集合所有字段，判断费用是否在系统中维护了的
                stringStringMap.remove("订单编号");
                List<OrderFee> fees = new ArrayList<>();
                stringStringMap.forEach((key, value) -> {
                    if (TypeStringUtils.TRANSPORT_FEE.equals(key)) {
                        // 运输费不做处理，由系统自动生成
                        return;
                    }
                    String currency = stringStringMap.get(String.format("%s币种", key));
                    if (currency == null) {
                        return;
                    }
                    if (!"null".equals(currency.trim()) && currencyList.stream().noneMatch(cu -> cu.contains(currency.trim()))) {
                        String text = String.format("【应收】订单编号【%s】一行运输费没有找到币种【%s】，系统存在的币种有【%s】", ghOrder.getOrderNumber(), currency.trim(), String.join(",", currencyList));
                        messageList.add(text);
                        return;
                    }
                    // 判断是否存在相同费用科目
                    Optional<OrderFee> feeOptional = orderFees.stream().filter(fee -> fee.getFeeName().equals(key)).findFirst();
                    if (feeOptional.isPresent()) {
                        // 除运输费外，判断费用是否锁定，如果是锁定，则不允许修改
                        OrderFee fee = feeOptional.get();
                        if (!TypeStringUtils.feeLockStatus.equals(fee.getStatus())) {
                            try {
                                fee.setCurrency(getCurrencyV2(currency.trim(), currencyList));
                                if (getMoney(value) == null) {
                                    return;
                                }
                                fee.setFeeCount(new Double((getMoney(value))));
                                // 系统发车时间为准，后面方便于统计应付费用
                                if (ghOrder.getActDepartureTime() != null) {
                                    fee.setCreateTime(ghOrder.getActDepartureTime().atStartOfDay());
                                }
                                if (fee.getFeeCount() <= 0) {
                                    return;
                                }
                                orderFeeRepository.save(fee);
                            } catch (Exception ig) {
                                ig.printStackTrace();
                            }
                        } else {
                            String text = String.format("【应收】订单编号【%s】一行【%s】已经锁定，不允许修改", ghOrder.getOrderNumber(), fee.getFeeName());
                            messageList.add(text);
                        }
                    } else {
                        OrderFee fee = new OrderFee();
                        fee.setId(snowFlakeFactory.nextId("OF"));
                        fee.setOrderId(ghOrder.getId());
                        fee.setFeeName(key);
                        try {
                            fee.setCurrency(getCurrencyV2(currency.trim(), currencyList));
                            if (getMoney(value) == null) {
                                return;
                            }
                            fee.setFeeCount(new Double((getMoney(value))));
                            // 系统发车时间为准，后面方便于统计应付费用
                            if (ghOrder.getActDepartureTime() != null) {
                                fee.setCreateTime(ghOrder.getActDepartureTime().atStartOfDay());
                            }
                            fee.setType(TypeStringUtils.feeInType);
                            if (fee.getFeeCount() >= 0) {
                                fees.add(fee);
                            }
                        } catch (Exception ig) {
                            ig.printStackTrace();
                        }
                    }
                });
                orderFeeRepository.save(fees);
            });
        }
        return messageList;
    }

    @Override
    public Set<String> batchCreateOutFee(List<Map<String, String>> dataList) {
        // 获取系统配置的币种列表
        List<ExchangeRate> exchangeRates = rateRepository.findAll();
        List<String> currencyList = new ArrayList<>();
        for (ExchangeRate exchangeRate : exchangeRates) {
            if (!currencyList.contains(exchangeRate.getFromRate())) {
                currencyList.add(exchangeRate.getFromRate());
            }
            if (!currencyList.contains(exchangeRate.getToRate())) {
                currencyList.add(exchangeRate.getToRate());
            }
        }
        Set<String> messageList = new HashSet<>();
        // 系统存在的费用科目
        List<String> feeItems = feeItemRepository.findAll().stream().map(FeeItem::getName).collect(Collectors.toList());
        // 所有供应商的简称
        List<String> carrierNames = carrierRepository.findAll().stream().map(Carrier::getName).collect(Collectors.toList());
        // 取出所有的订单号
        List<String> orderNumberList = new ArrayList<>();
        for (Map<String, String> stringStringMap : dataList) {
            String orderNumber = stringStringMap.get("订单编号");
            if (StringUtils.hasText(orderNumber)) {
                orderNumberList.add(orderNumber);
            }
        }
        List<GhOrder> ghOrders = ghOrderRepository.findAllByOrderNumberIn(orderNumberList);
        // 已经锁定的账单
        List<GhOrder> lockOrders = ghOrders.stream().filter(ghOrder -> BillType.STATUS_YJS.equals(ghOrder.getSettlement()) || BillType.STATUS_YJS.equals(ghOrder.getOutSettlement())).collect(Collectors.toList());
        if (lockOrders.size() > 0) {
            for (GhOrder lockOrder : lockOrders) {
                messageList.add(String.format("订单编号【%s】已封账，无法导入应付费用", lockOrder.getOrderNumber()));
            }
        }
        if (messageList.size() > 0) {
            return messageList;
        }
        int index = 1;
        for (Map<String, String> stringStringMap : dataList) {
            String orderNumber = stringStringMap.get("订单编号");
            if (StringUtils.hasText(orderNumber) && !orderNumber.toLowerCase().contains("null")) {
                boolean anyMatch = ghOrders.stream().anyMatch(order -> order.getOrderNumber().equals(orderNumber));
                if (!anyMatch) {
                    messageList.add(String.format("【应付】第【%d】行根据订单编号【%s】在系统找不到记录", index, orderNumber));
                }
            }
            int finalIndex = index;
            ghOrders.stream().filter(ghOrder -> ghOrder.getOrderNumber().equals(orderNumber)).findFirst().ifPresent(ghOrder -> {
                // 查出所有的费用
                List<OrderFee> orderFees = orderFeeRepository.findByOrderIdAndType(ghOrder.getId(), TypeStringUtils.feeOutType);
                // 判断之前是否已经生成了运输费，如果没有，需要生成运输费
                OrderFee existRecord = orderFees.stream().filter(orderFee -> TypeStringUtils.feeOutType.equals(orderFee.getType()) && TypeStringUtils.TRANSPORT_FEE.equals(orderFee.getFeeName())).findFirst().orElse(null);
                if (existRecord == null) {
                    existRecord = new OrderFee();
                    existRecord.setId(snowFlakeFactory.nextId("OF"));
                    existRecord.setOrderId(ghOrder.getId());
                    existRecord.setFeeName(TypeStringUtils.TRANSPORT_FEE);
                    existRecord.setType(TypeStringUtils.feeOutType);
                }
                String carrierKey = TypeStringUtils.TRANSPORT_FEE + "供应商";
                String carrierValueExcel = stringStringMap.get(carrierKey);
                if (carrierNames.contains(carrierValueExcel)) {
                    // 如果没有填入运输费，则自动计算
                    if (StringUtils.hasText(stringStringMap.get(TypeStringUtils.TRANSPORT_FEE))) {
                        existRecord.setCurrency(getCurrencyV2(stringStringMap.get(TypeStringUtils.TRANSPORT_FEE + "币种"), currencyList));
                        try {
                            existRecord.setFeeCount(new Double(stringStringMap.get(TypeStringUtils.TRANSPORT_FEE)));
                        } catch (Exception e) {
                            messageList.add(String.format("【应付】第【%d】行转换运输费【%s】失败，请检查", finalIndex, stringStringMap.get(TypeStringUtils.TRANSPORT_FEE)));
                        }
                    } else {
                        // 自动生成运输费
                        CalculateDto calculateDto = new CalculateDto();
                        BeanUtils.copyProperties(ghOrder, calculateDto);
                        calculateDto.setGhOrder(true);
                        // 计费方式按照提货日期
                        calculateDto.setCarrierId(carrierValueExcel);
                        existRecord.setCarrierId(carrierValueExcel);
                        calculateDto.setCalculateTime(ghOrder.getPickDate());
                        calculateDto.setFeeName(TypeStringUtils.TRANSPORT_FEE);
                        calculateDto.setCalculateType(CalculateTypeUtil.getCalculateType(ghOrder.getCalculateType()));
                        // 不提示
                        calculateDto.setNoTips(true);
                        List<PriceDto> priceDtos = calculateService.calculateOut(calculateDto);
                        Optional<PriceDto> first = priceDtos.stream().filter(priceDto -> priceDto.getFeeName().equals(TypeStringUtils.TRANSPORT_FEE)).findFirst();
                        if (first.isPresent()) {
                            existRecord.setFeeCount(first.get().getFeeCount());
                            existRecord.setCurrency(first.get().getCurrency());
                            existRecord.setCreateTime(ghOrder.getActDepartureTime().atStartOfDay());

                        }
                    }
                } else if (!"null".equals(carrierValueExcel)) {
                    messageList.add(String.format("【应付】第【%d】行根据供应商【%s】在系统找不到记录", finalIndex, carrierValueExcel));
                }
                if (messageList.size() == 0) {
                    // 保存运输费
                    orderFeeRepository.save(existRecord);
                }
                // 遍历集合所有字段，判断费用是否在系统中维护了的
                stringStringMap.remove("订单编号");
                // 重新设置供应商
                Set<String> carrierList = new HashSet<>();
                List<OrderFee> fees = new ArrayList<>();
                for (String feeName : feeItems) {
                    // 运输费自动算
                    if (TypeStringUtils.TRANSPORT_FEE.equals(feeName)) {
                        continue;
                    }
                    if (stringStringMap.containsKey(feeName)) {
                        // 对应费用的数值
                        String value = stringStringMap.get(feeName);
                        carrierKey = feeName + "供应商";
                        if (stringStringMap.containsKey(carrierKey)) {
                            // 所选供应商
                            carrierValueExcel = stringStringMap.get(carrierKey);
                            // 判断费用是否有值，并且是数字
                            if (StringUtils.hasText(value) && !value.toLowerCase().contains("null") && !isNumber(value)) {
                                messageList.add(String.format("【应付】第【%d】行【%s】不是数字类型，请修正", finalIndex, feeName));
                                continue;
                            }
                            // 获取费用币种
                            String currency = stringStringMap.get(String.format("%s币种", feeName));
                            if (!currency.equals("null") && currencyList.stream().noneMatch(cu -> cu.contains(currency))) {
                                String text = String.format("【应付】订单编号【%s】一行运输费没有找到币种【%s】，系统存在的币种有【%s】", ghOrder.getOrderNumber(), currency.trim(), String.join(",", currencyList));
                                messageList.add(text);
                                continue;
                            }
                            // 判断系统是否存在此供应商
                            if (carrierNames.contains(carrierValueExcel)) {
                                if (StringUtils.isEmpty(value) || "null".equals(value.toLowerCase().trim())) {
                                    // 如果费用没有值，那就要系统自动计算费用, 并且费用币种也要一致
                                    CalculateDto calculateDto = new CalculateDto();
                                    BeanUtils.copyProperties(ghOrder, calculateDto);
                                    calculateDto.setGhOrder(true);
                                    calculateDto.setNoTips(true);
                                    calculateDto.setCalculateTime(ghOrder.getPickDate());
                                    calculateDto.setCalculateType(CalculateTypeUtil.getCalculateType(ghOrder.getCalculateType()));
                                    calculateDto.setFeeName(feeName);
                                    calculateDto.setCarrierId(carrierValueExcel);
                                    List<PriceDto> outPriceList = calculateService.calculateOut(calculateDto);
                                    for (PriceDto priceDto : outPriceList) {
                                        // 币种必须一致
                                        if (!priceDto.getCurrency().equals(currency)) {
                                            continue;
                                        }
                                        existRecord = orderFees.stream().filter(orderFee -> feeName.equals(orderFee.getFeeName())).findFirst().orElse(null);
                                        if (existRecord == null) {
                                            // 新增对象
                                            existRecord = new OrderFee();
                                            existRecord.setId(snowFlakeFactory.nextId("OF"));
                                            existRecord.setOrderId(ghOrder.getId());
                                            existRecord.setFeeName(priceDto.getFeeName());
                                            existRecord.setType(TypeStringUtils.feeOutType);
                                        }
                                        // 判断是否锁定
                                        if (TypeStringUtils.feeLockStatus.equals(existRecord.getStatus())) {
                                            String text = String.format("【应付】订单编号【%s】一行【%s】已经锁定，不允许修改", ghOrder.getOrderNumber(), existRecord.getFeeName());
                                            messageList.add(text);
                                            continue;
                                        }
                                        existRecord.setCarrierId(carrierValueExcel);
                                        existRecord.setFeeCount(priceDto.getFeeCount());
                                        existRecord.setCurrency(priceDto.getCurrency());
                                        if (ghOrder.getActDepartureTime() != null) {
                                            existRecord.setCreateTime(ghOrder.getActDepartureTime().atStartOfDay());
                                        }
                                        // 添加到保存的列表
                                        fees.add(existRecord);
                                    }
                                    carrierList.add(carrierValueExcel);
                                    // 继续下一个费用
                                    continue;
                                }
                                carrierList.add(carrierValueExcel);
                                // 判断是否存在相同费用科目
                                Optional<OrderFee> feeOptional = orderFees.stream().filter(fee -> fee.getFeeName().equals(feeName)).findFirst();
                                if (feeOptional.isPresent()) {
                                    // 除运输费外，判断费用是否锁定，如果是锁定，则不允许修改
                                    OrderFee fee = feeOptional.get();
                                    if (!TypeStringUtils.feeLockStatus.equals(fee.getStatus())) {
                                        try {
                                            fee.setCurrency(getCurrencyV2(currency, currencyList));
                                            if (getMoney(value) == null) {
                                                continue;
                                            }
                                            fee.setFeeCount(new Double((getMoney(value))));
                                            // 系统发车时间为准，后面方便于统计应付费用
                                            if (ghOrder.getActDepartureTime() != null) {
                                                fee.setCreateTime(ghOrder.getActDepartureTime().atStartOfDay());
                                            }
                                            if (fee.getFeeCount() > 0) {
                                                fee.setCarrierId(carrierValueExcel);
                                                fees.add(fee);
                                            }
                                        } catch (Exception ig) {
                                            ig.printStackTrace();
                                        }
                                    } else {
                                        String text = String.format("【应付】订单编号【%s】一行【%s】已经锁定，不允许修改", ghOrder.getOrderNumber(), fee.getFeeName());
                                        messageList.add(text);
                                    }
                                } else {
                                    OrderFee fee = new OrderFee();
                                    fee.setId(snowFlakeFactory.nextId("OF"));
                                    fee.setOrderId(ghOrder.getId());
                                    fee.setCarrierId(carrierValueExcel);
                                    fee.setFeeName(feeName);
                                    try {
                                        fee.setCurrency(getCurrencyV2(currency, currencyList));
                                        if (getMoney(value) == null) {
                                            continue;
                                        }
                                        fee.setFeeCount(new Double((getMoney(value))));
                                        // 系统发车时间为准，后面方便于统计应付费用
                                        if (ghOrder.getActDepartureTime() != null) {
                                            fee.setCreateTime(ghOrder.getActDepartureTime().atStartOfDay());
                                        }
                                        fee.setType(TypeStringUtils.feeOutType);
                                        if (fee.getFeeCount() > 0) {
                                            fees.add(fee);
                                        }
                                    } catch (Exception ig) {
                                        ig.printStackTrace();
                                    }
                                }
                            } else if (StringUtils.hasText(carrierValueExcel) && !carrierValueExcel.contains("null")) {
                                messageList.add(String.format("供应商【%s】不存在", carrierValueExcel));
                            }
                        }
                    }
                }
                ghOrder.setCarrierName(String.join(",", carrierList));
                ghOrderRepository.save(ghOrder);
                orderFeeRepository.save(fees);
            });
            // 索引加1
            index++;
        }
        return messageList;
    }

    public static boolean isNumber(String str) {
        if (str == null) {
            return false;
        }
        if (str != null) {
            str = str.trim();
        }
        String reg = "^[0-9]+(.[0-9]+)?$";
        return str.matches(reg);
    }

    @Override
    public void unSetOrder(List<String> orderIds, String type) {
        List<GhOrder> ghOrders = ghOrderRepository.findAll(orderIds);
        List<OrderFee> orderFees = orderFeeRepository.findByOrderIdInAndType(orderIds, type);
        for (GhOrder ghOrder : ghOrders) {
            if (TypeStringUtils.feeOutType.equals(type)) {
                ghOrder.setOutSettlement(BillType.STATUS_WJS);
            } else {
                ghOrder.setSettlement(BillType.STATUS_WJS);
            }
            orderFees.stream().filter(fee -> fee.getType().equals(type) && fee.getOrderId().equals(ghOrder.getId())).forEach(orderFee -> orderFee.setStatus(TypeStringUtils.feeUnLockStatus));
        }
        ghOrderRepository.save(ghOrders);
        orderFeeRepository.save(orderFees);
    }

    @Override
    public void batchImportFee(List<GhOrderExportVo> importDatas, String opId) {
        List<String> bookNos = importDatas.stream().map(GhOrderExportVo::getBookNumber).filter(StringUtils::hasText).collect(Collectors.toList());
        List<GhOrder> ghOrders = ghOrderRepository.findByBookNumberIn(bookNos);
        // 取出所有的供应商
        List<Carrier> carriers = carrierRepository.findAll();
        // 取出所有机构
        List<Organization> organizations = organizationRepository.findAll();
        List<OrderFee> orderFees = orderFeeRepository.findByOrderIdIn(ghOrders.stream().map(GhOrder::getId).collect(Collectors.toList()));
        // 需要更新的综合列表
        List<GhOrder> updateOrders = new ArrayList<>();
        for (GhOrderExportVo importData : importDatas) {
            if (StringUtils.isEmpty(importData.getBookNumber())) {
                continue;
            }
            ghOrders.stream().filter(ghOrder -> ghOrder.getBookNumber().equals(importData.getBookNumber())).findFirst().ifPresent(ghOrder -> {
                // 检查当前单据下的机构是否存在供应商
                if (StringUtils.hasText(importData.getCarrier())) {
                    Carrier hasRecord = carriers.stream().filter(carrier -> carrier.getName().equals(importData.getCarrier()) && carrier.getOrganizationId().equals(ghOrder.getOrganizationId())).findFirst().orElse(null);
                    Organization organization = organizations.stream().filter(organization1 -> organization1.getId().equals(ghOrder.getOrganizationId())).findFirst().orElse(null);
                    Assert.isTrue(hasRecord != null, String.format("【%s】机构下供应商【%s】不存在", organization.getName(), importData.getCarrier()));
                }
                if (StringUtils.hasText(importData.getRemark())) {
                    ghOrder.setRemark(String.format("%s;%s", ghOrder.getRemark() == null ? "" : ghOrder.getRemark(), importData.getRemark()));
                    updateOrders.add(ghOrder);
                }
                OrderFee fee;
                if (importData.getTransportFee() != 0d) {
                    fee = orderFees.stream().filter(orderFee -> orderFee.getOrderId().equals(ghOrder.getId()) && TypeStringUtils.feeInType.equals(orderFee.getType()) && TypeStringUtils.TRANSPORT_FEE.equals(orderFee.getFeeName())).findFirst().orElse(null);
                    if (fee != null) {
                        fee.setFeeCount(importData.getTransportFee());
                        fee.setCurrency(importData.getInCurrency());
                    } else {
                        fee = new OrderFee();
                        fee.setFeeName(TypeStringUtils.TRANSPORT_FEE);
                        fee.setFeeCount(importData.getTransportFee());
                        fee.setCurrency(importData.getInCurrency());
                        fee.setType(TypeStringUtils.feeInType);
                        fee.setOrderId(ghOrder.getId());
                        fee.setId(snowFlakeFactory.nextId("OF"));
                    }
                    orderFeeRepository.save(fee);
                }
                if (importData.getOutTransportFee() != 0d) {
                    fee = orderFees.stream().filter(orderFee -> orderFee.getOrderId().equals(ghOrder.getId()) && TypeStringUtils.feeOutType.equals(orderFee.getType()) && TypeStringUtils.TRANSPORT_FEE.equals(orderFee.getFeeName())).findFirst().orElse(null);
                    if (fee != null) {
                        fee.setFeeCount(importData.getOutTransportFee());
                        fee.setCurrency(importData.getOutCurrency());
                        fee.setCarrierId(importData.getCarrier());
                        if (StringUtils.hasText(ghOrder.getCarrierName()) && !ghOrder.getCarrierName().contains(importData.getCarrier())) {
                            ghOrder.setCarrierName(String.format("%s;%s", ghOrder.getCarrierName(), importData.getCarrier()));
                        } else {
                            ghOrder.setCarrierName(importData.getCarrier());
                        }
                        updateOrders.add(ghOrder);
                    } else {
                        fee = new OrderFee();
                        fee.setFeeName(TypeStringUtils.TRANSPORT_FEE);
                        fee.setFeeCount(importData.getOutTransportFee());
                        fee.setCurrency(importData.getOutCurrency());
                        fee.setType(TypeStringUtils.feeOutType);
                        fee.setOrderId(ghOrder.getId());
                        fee.setCarrierId(importData.getCarrier());
                        if (StringUtils.hasText(ghOrder.getCarrierName()) && !ghOrder.getCarrierName().contains(importData.getCarrier())) {
                            ghOrder.setCarrierName(String.format("%s;%s", ghOrder.getCarrierName(), importData.getCarrier()));
                        } else {
                            ghOrder.setCarrierName(importData.getCarrier());
                        }
                        updateOrders.add(ghOrder);
                        fee.setId(snowFlakeFactory.nextId("OF"));
                    }
                    orderFeeRepository.save(fee);
                }
            });
        }
        if (updateOrders.size() > 0) {
            ghOrderRepository.save(updateOrders);
        }
    }
}
